AIDL BufferPool implementation (HIDL -> AIDL)
Bug: 254050250
Test: m
Change-Id: I0d7bae2c01bd480d1e99f4b39c4a9013a2828897
diff --git a/media/bufferpool/aidl/default/Accessor.cpp b/media/bufferpool/aidl/default/Accessor.cpp
index e05b12a..3d206ac 100644
--- a/media/bufferpool/aidl/default/Accessor.cpp
+++ b/media/bufferpool/aidl/default/Accessor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,22 +13,60 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#define LOG_TAG "BufferPoolConnection"
+#define LOG_TAG "AidlBufferPoolAcc"
+//#define LOG_NDEBUG 0
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <time.h>
+#include <unistd.h>
+#include <utils/Log.h>
+#include <thread>
#include "Accessor.h"
-#include "AccessorImpl.h"
#include "Connection.h"
+#include "DataHelper.h"
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
-namespace V2_0 {
-namespace implementation {
+namespace aidl::android::hardware::media::bufferpool2::implementation {
+
+namespace {
+ static constexpr nsecs_t kEvictGranularityNs = 1000000000; // 1 sec
+ static constexpr nsecs_t kEvictDurationNs = 5000000000; // 5 secs
+}
+
+#ifdef __ANDROID_VNDK__
+static constexpr uint32_t kSeqIdVndkBit = 1U << 31;
+#else
+static constexpr uint32_t kSeqIdVndkBit = 0;
+#endif
+
+static constexpr uint32_t kSeqIdMax = 0x7fffffff;
+uint32_t Accessor::sSeqId = time(nullptr) & kSeqIdMax;
+
+namespace {
+// anonymous namespace
+static std::shared_ptr<ConnectionDeathRecipient> sConnectionDeathRecipient =
+ std::make_shared<ConnectionDeathRecipient>();
+
+void serviceDied(void *cookie) {
+ if (sConnectionDeathRecipient) {
+ sConnectionDeathRecipient->onDead(cookie);
+ }
+}
+}
+
+std::shared_ptr<ConnectionDeathRecipient> Accessor::getConnectionDeathRecipient() {
+ return sConnectionDeathRecipient;
+}
+
+ConnectionDeathRecipient::ConnectionDeathRecipient() {
+ mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(
+ AIBinder_DeathRecipient_new(serviceDied));
+}
void ConnectionDeathRecipient::add(
int64_t connectionId,
- const sp<Accessor> &accessor) {
+ const std::shared_ptr<Accessor> &accessor) {
std::lock_guard<std::mutex> lock(mLock);
if (mAccessors.find(connectionId) == mAccessors.end()) {
mAccessors.insert(std::make_pair(connectionId, accessor));
@@ -40,7 +78,7 @@
mAccessors.erase(connectionId);
auto it = mConnectionToCookie.find(connectionId);
if (it != mConnectionToCookie.end()) {
- uint64_t cookie = it->second;
+ void * cookie = it->second;
mConnectionToCookie.erase(it);
auto cit = mCookieToConnections.find(cookie);
if (cit != mCookieToConnections.end()) {
@@ -53,7 +91,7 @@
}
void ConnectionDeathRecipient::addCookieToConnection(
- uint64_t cookie,
+ void *cookie,
int64_t connectionId) {
std::lock_guard<std::mutex> lock(mLock);
if (mAccessors.find(connectionId) == mAccessors.end()) {
@@ -69,11 +107,8 @@
}
}
-void ConnectionDeathRecipient::serviceDied(
- uint64_t cookie,
- const wp<::android::hidl::base::V1_0::IBase>& /* who */
- ) {
- std::map<int64_t, const wp<Accessor>> connectionsToClose;
+void ConnectionDeathRecipient::onDead(void *cookie) {
+ std::map<int64_t, const std::weak_ptr<Accessor>> connectionsToClose;
{
std::lock_guard<std::mutex> lock(mLock);
@@ -92,9 +127,9 @@
}
if (connectionsToClose.size() > 0) {
- sp<Accessor> accessor;
+ std::shared_ptr<Accessor> accessor;
for (auto it = connectionsToClose.begin(); it != connectionsToClose.end(); ++it) {
- accessor = it->second.promote();
+ accessor = it->second.lock();
if (accessor) {
accessor->close(it->first);
@@ -104,127 +139,371 @@
}
}
-namespace {
-static sp<ConnectionDeathRecipient> sConnectionDeathRecipient =
- new ConnectionDeathRecipient();
+AIBinder_DeathRecipient *ConnectionDeathRecipient::getRecipient() {
+ return mDeathRecipient.get();
}
-sp<ConnectionDeathRecipient> Accessor::getConnectionDeathRecipient() {
- return sConnectionDeathRecipient;
-}
-
-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,
- connect_cb _hidl_cb) {
- sp<Connection> connection;
+::ndk::ScopedAStatus Accessor::connect(const std::shared_ptr<::aidl::android::hardware::media::bufferpool2::IObserver>& in_observer, ::aidl::android::hardware::media::bufferpool2::IAccessor::ConnectionInfo* _aidl_return) {
+ std::shared_ptr<Connection> connection;
ConnectionId connectionId;
uint32_t msgId;
- const StatusDescriptor* fmqDesc;
- const InvalidationDescriptor* invDesc;
-
- ResultStatus status = connect(
- observer, false, &connection, &connectionId, &msgId, &fmqDesc, &invDesc);
+ StatusDescriptor statusDesc;
+ InvalidationDescriptor invDesc;
+ BufferPoolStatus status = connect(
+ in_observer, false, &connection, &connectionId, &msgId, &statusDesc, &invDesc);
if (status == ResultStatus::OK) {
- _hidl_cb(status, connection, connectionId, msgId, *fmqDesc, *invDesc);
- } else {
- _hidl_cb(status, nullptr, -1LL, 0,
- android::hardware::MQDescriptorSync<BufferStatusMessage>(
- std::vector<android::hardware::GrantorDescriptor>(),
- nullptr /* nhandle */, 0 /* size */),
- android::hardware::MQDescriptorUnsync<BufferInvalidationMessage>(
- std::vector<android::hardware::GrantorDescriptor>(),
- nullptr /* nhandle */, 0 /* size */));
+ _aidl_return->connection = connection;
+ _aidl_return->connectionId = connectionId;
+ _aidl_return->msgId = msgId;
+ _aidl_return->toFmqDesc = std::move(statusDesc);
+ _aidl_return->fromFmqDesc = std::move(invDesc);
+ return ::ndk::ScopedAStatus::ok();
}
- return Void();
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(status);
}
Accessor::Accessor(const std::shared_ptr<BufferPoolAllocator> &allocator)
- : mImpl(new Impl(allocator)) {}
+ : mAllocator(allocator), mScheduleEvictTs(0) {}
Accessor::~Accessor() {
}
bool Accessor::isValid() {
- return (bool)mImpl && mImpl->isValid();
+ return mBufferPool.isValid();
}
-ResultStatus Accessor::flush() {
- if (mImpl) {
- mImpl->flush();
- return ResultStatus::OK;
- }
- return ResultStatus::CRITICAL_ERROR;
+BufferPoolStatus Accessor::flush() {
+ std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
+ mBufferPool.processStatusMessages();
+ mBufferPool.flush(ref<Accessor>());
+ return ResultStatus::OK;
}
-ResultStatus Accessor::allocate(
+BufferPoolStatus Accessor::allocate(
ConnectionId connectionId,
const std::vector<uint8_t> ¶ms,
BufferId *bufferId, const native_handle_t** handle) {
- if (mImpl) {
- return mImpl->allocate(connectionId, params, bufferId, handle);
+ std::unique_lock<std::mutex> lock(mBufferPool.mMutex);
+ mBufferPool.processStatusMessages();
+ BufferPoolStatus status = ResultStatus::OK;
+ if (!mBufferPool.getFreeBuffer(mAllocator, params, bufferId, handle)) {
+ lock.unlock();
+ std::shared_ptr<BufferPoolAllocation> alloc;
+ size_t allocSize;
+ status = mAllocator->allocate(params, &alloc, &allocSize);
+ lock.lock();
+ if (status == ResultStatus::OK) {
+ status = mBufferPool.addNewBuffer(alloc, allocSize, params, bufferId, handle);
+ }
+ ALOGV("create a buffer %d : %u %p",
+ status == ResultStatus::OK, *bufferId, *handle);
}
- return ResultStatus::CRITICAL_ERROR;
+ if (status == ResultStatus::OK) {
+ // TODO: handle ownBuffer failure
+ mBufferPool.handleOwnBuffer(connectionId, *bufferId);
+ }
+ mBufferPool.cleanUp();
+ scheduleEvictIfNeeded();
+ return status;
}
-ResultStatus Accessor::fetch(
+BufferPoolStatus Accessor::fetch(
ConnectionId connectionId, TransactionId transactionId,
BufferId bufferId, const native_handle_t** handle) {
- if (mImpl) {
- return mImpl->fetch(connectionId, transactionId, bufferId, handle);
- }
- return ResultStatus::CRITICAL_ERROR;
-}
-
-ResultStatus Accessor::connect(
- const sp<IObserver> &observer, bool local,
- sp<Connection> *connection, ConnectionId *pConnectionId,
- uint32_t *pMsgId,
- const StatusDescriptor** statusDescPtr,
- const InvalidationDescriptor** invDescPtr) {
- if (mImpl) {
- ResultStatus status = mImpl->connect(
- this, observer, connection, pConnectionId, pMsgId,
- statusDescPtr, invDescPtr);
- if (!local && status == ResultStatus::OK) {
- sp<Accessor> accessor(this);
- sConnectionDeathRecipient->add(*pConnectionId, accessor);
+ std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
+ mBufferPool.processStatusMessages();
+ auto found = mBufferPool.mTransactions.find(transactionId);
+ if (found != mBufferPool.mTransactions.end() &&
+ contains(&mBufferPool.mPendingTransactions,
+ connectionId, transactionId)) {
+ if (found->second->mSenderValidated &&
+ found->second->mStatus == BufferStatus::TRANSFER_FROM &&
+ found->second->mBufferId == bufferId) {
+ found->second->mStatus = BufferStatus::TRANSFER_FETCH;
+ auto bufferIt = mBufferPool.mBuffers.find(bufferId);
+ if (bufferIt != mBufferPool.mBuffers.end()) {
+ mBufferPool.mStats.onBufferFetched();
+ *handle = bufferIt->second->handle();
+ return ResultStatus::OK;
+ }
}
- return status;
}
+ mBufferPool.cleanUp();
+ scheduleEvictIfNeeded();
return ResultStatus::CRITICAL_ERROR;
}
-ResultStatus Accessor::close(ConnectionId connectionId) {
- if (mImpl) {
- ResultStatus status = mImpl->close(connectionId);
- sConnectionDeathRecipient->remove(connectionId);
- return status;
+BufferPoolStatus Accessor::connect(
+ const std::shared_ptr<IObserver> &observer, bool local,
+ std::shared_ptr<Connection> *connection, ConnectionId *pConnectionId,
+ uint32_t *pMsgId,
+ StatusDescriptor* statusDescPtr,
+ InvalidationDescriptor* invDescPtr) {
+ std::shared_ptr<Connection> newConnection = ::ndk::SharedRefBase::make<Connection>();
+ BufferPoolStatus status = ResultStatus::CRITICAL_ERROR;
+ {
+ std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
+ if (newConnection) {
+ int32_t pid = getpid();
+ ConnectionId id = (int64_t)pid << 32 | sSeqId | kSeqIdVndkBit;
+ status = mBufferPool.mObserver.open(id, statusDescPtr);
+ if (status == ResultStatus::OK) {
+ newConnection->initialize(ref<Accessor>(), id);
+ *connection = newConnection;
+ *pConnectionId = id;
+ *pMsgId = mBufferPool.mInvalidation.mInvalidationId;
+ mBufferPool.mConnectionIds.insert(id);
+ mBufferPool.mInvalidationChannel.getDesc(invDescPtr);
+ mBufferPool.mInvalidation.onConnect(id, observer);
+ if (sSeqId == kSeqIdMax) {
+ sSeqId = 0;
+ } else {
+ ++sSeqId;
+ }
+ }
+
+ }
+ mBufferPool.processStatusMessages();
+ mBufferPool.cleanUp();
+ scheduleEvictIfNeeded();
}
- return ResultStatus::CRITICAL_ERROR;
+ if (!local && status == ResultStatus::OK) {
+ std::shared_ptr<Accessor> accessor(ref<Accessor>());
+ sConnectionDeathRecipient->add(*pConnectionId, accessor);
+ }
+ return status;
+}
+
+BufferPoolStatus Accessor::close(ConnectionId connectionId) {
+ {
+ std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
+ ALOGV("connection close %lld: %u", (long long)connectionId, mBufferPool.mInvalidation.mId);
+ mBufferPool.processStatusMessages();
+ mBufferPool.handleClose(connectionId);
+ mBufferPool.mObserver.close(connectionId);
+ mBufferPool.mInvalidation.onClose(connectionId);
+ // Since close# will be called after all works are finished, it is OK to
+ // evict unused buffers.
+ mBufferPool.cleanUp(true);
+ scheduleEvictIfNeeded();
+ }
+ sConnectionDeathRecipient->remove(connectionId);
+ return ResultStatus::OK;
}
void Accessor::cleanUp(bool clearCache) {
- if (mImpl) {
- mImpl->cleanUp(clearCache);
+ // transaction timeout, buffer caching TTL handling
+ std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
+ mBufferPool.processStatusMessages();
+ mBufferPool.cleanUp(clearCache);
+}
+
+void Accessor::handleInvalidateAck() {
+ std::map<ConnectionId, const std::shared_ptr<IObserver>> observers;
+ uint32_t invalidationId;
+ {
+ std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
+ mBufferPool.processStatusMessages();
+ mBufferPool.mInvalidation.onHandleAck(&observers, &invalidationId);
+ }
+ // Do not hold lock for send invalidations
+ size_t deadClients = 0;
+ for (auto it = observers.begin(); it != observers.end(); ++it) {
+ const std::shared_ptr<IObserver> observer = it->second;
+ if (observer) {
+ ::ndk::ScopedAStatus status = observer->onMessage(it->first, invalidationId);
+ if (!status.isOk()) {
+ ++deadClients;
+ }
+ }
+ }
+ if (deadClients > 0) {
+ ALOGD("During invalidation found %zu dead clients", deadClients);
}
}
-//IAccessor* HIDL_FETCH_IAccessor(const char* /* name */) {
-// return new Accessor();
-//}
+void Accessor::invalidatorThread(
+ std::map<uint32_t, const std::weak_ptr<Accessor>> &accessors,
+ std::mutex &mutex,
+ std::condition_variable &cv,
+ bool &ready) {
+ constexpr uint32_t NUM_SPIN_TO_INCREASE_SLEEP = 1024;
+ constexpr uint32_t NUM_SPIN_TO_LOG = 1024*8;
+ constexpr useconds_t MAX_SLEEP_US = 10000;
+ uint32_t numSpin = 0;
+ useconds_t sleepUs = 1;
-} // namespace implementation
-} // namespace V2_0
-} // namespace bufferpool
-} // namespace media
-} // namespace hardware
-} // namespace android
+ while(true) {
+ std::map<uint32_t, const std::weak_ptr<Accessor>> copied;
+ {
+ std::unique_lock<std::mutex> lock(mutex);
+ while (!ready) {
+ numSpin = 0;
+ sleepUs = 1;
+ cv.wait(lock);
+ }
+ copied.insert(accessors.begin(), accessors.end());
+ }
+ std::list<ConnectionId> erased;
+ for (auto it = copied.begin(); it != copied.end(); ++it) {
+ const std::shared_ptr<Accessor> acc = it->second.lock();
+ if (!acc) {
+ erased.push_back(it->first);
+ } else {
+ acc->handleInvalidateAck();
+ }
+ }
+ {
+ std::unique_lock<std::mutex> lock(mutex);
+ for (auto it = erased.begin(); it != erased.end(); ++it) {
+ accessors.erase(*it);
+ }
+ if (accessors.size() == 0) {
+ ready = false;
+ } else {
+ // N.B. Since there is not a efficient way to wait over FMQ,
+ // polling over the FMQ is the current way to prevent draining
+ // CPU.
+ lock.unlock();
+ ++numSpin;
+ if (numSpin % NUM_SPIN_TO_INCREASE_SLEEP == 0 &&
+ sleepUs < MAX_SLEEP_US) {
+ sleepUs *= 10;
+ }
+ if (numSpin % NUM_SPIN_TO_LOG == 0) {
+ ALOGW("invalidator thread spinning");
+ }
+ ::usleep(sleepUs);
+ }
+ }
+ }
+}
+
+Accessor::AccessorInvalidator::AccessorInvalidator() : mReady(false) {
+ std::thread invalidator(
+ invalidatorThread,
+ std::ref(mAccessors),
+ std::ref(mMutex),
+ std::ref(mCv),
+ std::ref(mReady));
+ invalidator.detach();
+}
+
+void Accessor::AccessorInvalidator::addAccessor(
+ uint32_t accessorId, const std::weak_ptr<Accessor> &accessor) {
+ bool notify = false;
+ std::unique_lock<std::mutex> lock(mMutex);
+ if (mAccessors.find(accessorId) == mAccessors.end()) {
+ if (!mReady) {
+ mReady = true;
+ notify = true;
+ }
+ mAccessors.emplace(accessorId, accessor);
+ ALOGV("buffer invalidation added bp:%u %d", accessorId, notify);
+ }
+ lock.unlock();
+ if (notify) {
+ mCv.notify_one();
+ }
+}
+
+void Accessor::AccessorInvalidator::delAccessor(uint32_t accessorId) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mAccessors.erase(accessorId);
+ ALOGV("buffer invalidation deleted bp:%u", accessorId);
+ if (mAccessors.size() == 0) {
+ mReady = false;
+ }
+}
+
+std::unique_ptr<Accessor::AccessorInvalidator> Accessor::sInvalidator;
+
+void Accessor::createInvalidator() {
+ if (!sInvalidator) {
+ sInvalidator = std::make_unique<Accessor::AccessorInvalidator>();
+ }
+}
+
+void Accessor::evictorThread(
+ std::map<const std::weak_ptr<Accessor>, nsecs_t, std::owner_less<>> &accessors,
+ std::mutex &mutex,
+ std::condition_variable &cv) {
+ std::list<const std::weak_ptr<Accessor>> evictList;
+ while (true) {
+ int expired = 0;
+ int evicted = 0;
+ {
+ nsecs_t now = systemTime();
+ std::unique_lock<std::mutex> lock(mutex);
+ while (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> 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::AccessorEvictor::AccessorEvictor() {
+ std::thread evictor(
+ evictorThread,
+ std::ref(mAccessors),
+ std::ref(mMutex),
+ std::ref(mCv));
+ evictor.detach();
+}
+
+void Accessor::AccessorEvictor::addAccessor(
+ const std::weak_ptr<Accessor> &accessor, nsecs_t ts) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ bool notify = mAccessors.empty();
+ auto it = mAccessors.find(accessor);
+ if (it == mAccessors.end()) {
+ mAccessors.emplace(accessor, ts);
+ } else {
+ it->second = ts;
+ }
+ if (notify) {
+ mCv.notify_one();
+ }
+}
+
+std::unique_ptr<Accessor::AccessorEvictor> Accessor::sEvictor;
+
+void Accessor::createEvictor() {
+ if (!sEvictor) {
+ sEvictor = std::make_unique<Accessor::AccessorEvictor>();
+ }
+}
+
+void Accessor::scheduleEvictIfNeeded() {
+ nsecs_t now = systemTime();
+
+ if (now > (mScheduleEvictTs + kEvictGranularityNs)) {
+ mScheduleEvictTs = now;
+ sEvictor->addAccessor(ref<Accessor>(), now);
+ }
+}
+
+} // namespace aidl::android::hardware::media::bufferpool2::implemntation {
diff --git a/media/bufferpool/aidl/default/Accessor.h b/media/bufferpool/aidl/default/Accessor.h
index 8b43301..85e2fa7 100644
--- a/media/bufferpool/aidl/default/Accessor.h
+++ b/media/bufferpool/aidl/default/Accessor.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,73 +14,65 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_ACCESSOR_H
-#define ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_ACCESSOR_H
+#pragma once
-#include <android/hardware/media/bufferpool/2.0/IAccessor.h>
-#include <android/hardware/media/bufferpool/2.0/IObserver.h>
-#include <bufferpool/BufferPoolTypes.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-#include "BufferStatus.h"
+#include <aidl/android/hardware/media/bufferpool2/BnAccessor.h>
+#include <aidl/android/hardware/media/bufferpool2/IObserver.h>
+#include <bufferpool2/BufferPoolTypes.h>
+#include <memory>
+#include <map>
#include <set>
+#include <condition_variable>
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
-namespace V2_0 {
-namespace implementation {
+#include "BufferPool.h"
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
+namespace aidl::android::hardware::media::bufferpool2::implementation {
-struct Accessor;
struct Connection;
+using ::aidl::android::hardware::media::bufferpool2::IObserver;
+using ::aidl::android::hardware::media::bufferpool2::IAccessor;
/**
* Receives death notifications from remote connections.
* On death notifications, the connections are closed and used resources
* are released.
*/
-struct ConnectionDeathRecipient : public hardware::hidl_death_recipient {
+struct ConnectionDeathRecipient {
+ ConnectionDeathRecipient();
/**
* Registers a newly connected connection from remote processes.
*/
- void add(int64_t connectionId, const sp<Accessor> &accessor);
+ void add(int64_t connectionId, const std::shared_ptr<Accessor> &accessor);
/**
* Removes a connection.
*/
void remove(int64_t connectionId);
- void addCookieToConnection(uint64_t cookie, int64_t connectionId);
+ void addCookieToConnection(void *cookie, int64_t connectionId);
- virtual void serviceDied(
- uint64_t /* cookie */,
- const wp<::android::hidl::base::V1_0::IBase>& /* who */
- ) override;
+ void onDead(void *cookie);
+
+ AIBinder_DeathRecipient *getRecipient();
private:
+ ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+
std::mutex mLock;
- std::map<uint64_t, std::set<int64_t>> mCookieToConnections;
- std::map<int64_t, uint64_t> mConnectionToCookie;
- std::map<int64_t, const wp<Accessor>> mAccessors;
+ std::map<void *, std::set<int64_t>> mCookieToConnections;
+ std::map<int64_t, void *> mConnectionToCookie;
+ std::map<int64_t, const std::weak_ptr<Accessor>> mAccessors;
};
/**
* A buffer pool accessor which enables a buffer pool to communicate with buffer
* pool clients. 1:1 correspondense holds between a buffer pool and an accessor.
*/
-struct Accessor : public IAccessor {
- // Methods from ::android::hardware::media::bufferpool::V2_0::IAccessor follow.
- Return<void> connect(const sp<::android::hardware::media::bufferpool::V2_0::IObserver>& observer, connect_cb _hidl_cb) override;
+struct Accessor : public BnAccessor {
+ // Methods from ::aidl::android::hardware::media::bufferpool2::IAccessor.
+ ::ndk::ScopedAStatus connect(const std::shared_ptr<IObserver>& in_observer,
+ IAccessor::ConnectionInfo* _aidl_return) override;
/**
* Creates a buffer pool accessor which uses the specified allocator.
@@ -96,7 +88,7 @@
bool isValid();
/** Invalidates all buffers which are owned by bufferpool */
- ResultStatus flush();
+ BufferPoolStatus flush();
/** Allocates a buffer from a buffer pool.
*
@@ -109,7 +101,7 @@
* NO_MEMORY when there is no memory.
* CRITICAL_ERROR otherwise.
*/
- ResultStatus allocate(
+ BufferPoolStatus allocate(
ConnectionId connectionId,
const std::vector<uint8_t>& params,
BufferId *bufferId,
@@ -127,7 +119,7 @@
* NO_MEMORY when there is no memory.
* CRITICAL_ERROR otherwise.
*/
- ResultStatus fetch(
+ BufferPoolStatus fetch(
ConnectionId connectionId,
TransactionId transactionId,
BufferId bufferId,
@@ -153,13 +145,13 @@
* NO_MEMORY when there is no memory.
* CRITICAL_ERROR otherwise.
*/
- ResultStatus connect(
- const sp<IObserver>& observer,
+ BufferPoolStatus connect(
+ const std::shared_ptr<IObserver>& observer,
bool local,
- sp<Connection> *connection, ConnectionId *pConnectionId,
+ std::shared_ptr<Connection> *connection, ConnectionId *pConnectionId,
uint32_t *pMsgId,
- const StatusDescriptor** statusDescPtr,
- const InvalidationDescriptor** invDescPtr);
+ StatusDescriptor* statusDescPtr,
+ InvalidationDescriptor* invDescPtr);
/**
* Closes the specified connection to the client.
@@ -169,10 +161,10 @@
* @return OK when the connection is closed.
* CRITICAL_ERROR otherwise.
*/
- ResultStatus close(ConnectionId connectionId);
+ BufferPoolStatus close(ConnectionId connectionId);
/**
- * Processes pending buffer status messages and perfoms periodic cache
+ * Processes pending buffer status messages and performs periodic cache
* cleaning.
*
* @param clearCache if clearCache is true, it frees all buffers waiting
@@ -181,24 +173,66 @@
void cleanUp(bool clearCache);
/**
- * Gets a hidl_death_recipient for remote connection death.
+ * ACK on buffer invalidation messages
*/
- static sp<ConnectionDeathRecipient> getConnectionDeathRecipient();
+ void handleInvalidateAck();
+
+ /**
+ * Gets a death_recipient for remote connection death.
+ */
+ static std::shared_ptr<ConnectionDeathRecipient> getConnectionDeathRecipient();
static void createInvalidator();
static void createEvictor();
private:
- class Impl;
- std::shared_ptr<Impl> mImpl;
+ // ConnectionId = pid : (timestamp_created + seqId)
+ // in order to guarantee uniqueness for each connection
+ static uint32_t sSeqId;
+
+ const std::shared_ptr<BufferPoolAllocator> mAllocator;
+ nsecs_t mScheduleEvictTs;
+ BufferPool mBufferPool;
+
+ struct AccessorInvalidator {
+ std::map<uint32_t, const std::weak_ptr<Accessor>> mAccessors;
+ std::mutex mMutex;
+ std::condition_variable mCv;
+ bool mReady;
+
+ AccessorInvalidator();
+ void addAccessor(uint32_t accessorId, const std::weak_ptr<Accessor> &accessor);
+ void delAccessor(uint32_t accessorId);
+ };
+
+ static std::unique_ptr<AccessorInvalidator> sInvalidator;
+
+ static void invalidatorThread(
+ std::map<uint32_t, const std::weak_ptr<Accessor>> &accessors,
+ std::mutex &mutex,
+ std::condition_variable &cv,
+ bool &ready);
+
+ struct AccessorEvictor {
+ std::map<const std::weak_ptr<Accessor>, nsecs_t, std::owner_less<>> mAccessors;
+ std::mutex mMutex;
+ std::condition_variable mCv;
+
+ AccessorEvictor();
+ void addAccessor(const std::weak_ptr<Accessor> &accessor, nsecs_t ts);
+ };
+
+ static std::unique_ptr<AccessorEvictor> sEvictor;
+
+ static void evictorThread(
+ std::map<const std::weak_ptr<Accessor>, nsecs_t, std::owner_less<>> &accessors,
+ std::mutex &mutex,
+ std::condition_variable &cv);
+
+ void scheduleEvictIfNeeded();
+
+ friend struct BufferPool;
};
-} // namespace implementation
-} // namespace V2_0
-} // namespace bufferpool
-} // namespace media
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_ACCESSOR_H
+} // namespace aidl::android::hardware::media::bufferpool2::implementation
diff --git a/media/bufferpool/aidl/default/AccessorImpl.cpp b/media/bufferpool/aidl/default/AccessorImpl.cpp
deleted file mode 100644
index 1d2562e..0000000
--- a/media/bufferpool/aidl/default/AccessorImpl.cpp
+++ /dev/null
@@ -1,993 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "BufferPoolAccessor2.0"
-//#define LOG_NDEBUG 0
-
-#include <sys/types.h>
-#include <stdint.h>
-#include <time.h>
-#include <unistd.h>
-#include <utils/Log.h>
-#include <thread>
-#include "AccessorImpl.h"
-#include "Connection.h"
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
-namespace V2_0 {
-namespace implementation {
-
-namespace {
- static constexpr int64_t kCleanUpDurationUs = 500000; // TODO tune 0.5 sec
- static constexpr int64_t kLogDurationUs = 5000000; // 5 secs
-
- static constexpr size_t kMinAllocBytesForEviction = 1024*1024*15;
- static constexpr size_t kMinBufferCountForEviction = 25;
- static constexpr size_t kMaxUnusedBufferCount = 64;
- static constexpr size_t kUnusedBufferCountTarget = kMaxUnusedBufferCount - 16;
-
- static constexpr nsecs_t kEvictGranularityNs = 1000000000; // 1 sec
- static constexpr nsecs_t kEvictDurationNs = 5000000000; // 5 secs
-}
-
-// Buffer structure in bufferpool process
-struct InternalBuffer {
- BufferId mId;
- size_t mOwnerCount;
- size_t mTransactionCount;
- const std::shared_ptr<BufferPoolAllocation> mAllocation;
- const size_t mAllocSize;
- const std::vector<uint8_t> mConfig;
- bool mInvalidated;
-
- InternalBuffer(
- BufferId id,
- const std::shared_ptr<BufferPoolAllocation> &alloc,
- const size_t allocSize,
- const std::vector<uint8_t> &allocConfig)
- : mId(id), mOwnerCount(0), mTransactionCount(0),
- mAllocation(alloc), mAllocSize(allocSize), mConfig(allocConfig),
- mInvalidated(false) {}
-
- const native_handle_t *handle() {
- return mAllocation->handle();
- }
-
- void invalidate() {
- mInvalidated = true;
- }
-};
-
-struct TransactionStatus {
- TransactionId mId;
- BufferId mBufferId;
- ConnectionId mSender;
- ConnectionId mReceiver;
- BufferStatus mStatus;
- int64_t mTimestampUs;
- bool mSenderValidated;
-
- TransactionStatus(const BufferStatusMessage &message, int64_t timestampUs) {
- mId = message.transactionId;
- mBufferId = message.bufferId;
- mStatus = message.newStatus;
- mTimestampUs = timestampUs;
- if (mStatus == BufferStatus::TRANSFER_TO) {
- mSender = message.connectionId;
- mReceiver = message.targetConnectionId;
- mSenderValidated = true;
- } else {
- mSender = -1LL;
- mReceiver = message.connectionId;
- mSenderValidated = false;
- }
- }
-};
-
-// Helper template methods for handling map of set.
-template<class T, class U>
-bool insert(std::map<T, std::set<U>> *mapOfSet, T key, U value) {
- auto iter = mapOfSet->find(key);
- if (iter == mapOfSet->end()) {
- std::set<U> valueSet{value};
- mapOfSet->insert(std::make_pair(key, valueSet));
- return true;
- } else if (iter->second.find(value) == iter->second.end()) {
- iter->second.insert(value);
- return true;
- }
- return false;
-}
-
-template<class T, class U>
-bool erase(std::map<T, std::set<U>> *mapOfSet, T key, U value) {
- bool ret = false;
- auto iter = mapOfSet->find(key);
- if (iter != mapOfSet->end()) {
- if (iter->second.erase(value) > 0) {
- ret = true;
- }
- if (iter->second.size() == 0) {
- mapOfSet->erase(iter);
- }
- }
- return ret;
-}
-
-template<class T, class U>
-bool contains(std::map<T, std::set<U>> *mapOfSet, T key, U value) {
- auto iter = mapOfSet->find(key);
- if (iter != mapOfSet->end()) {
- auto setIter = iter->second.find(value);
- return setIter != iter->second.end();
- }
- return false;
-}
-
-#ifdef __ANDROID_VNDK__
-static constexpr uint32_t kSeqIdVndkBit = 1U << 31;
-#else
-static constexpr uint32_t kSeqIdVndkBit = 0;
-#endif
-
-static constexpr uint32_t kSeqIdMax = 0x7fffffff;
-uint32_t Accessor::Impl::sSeqId = time(nullptr) & kSeqIdMax;
-
-Accessor::Impl::Impl(
- const std::shared_ptr<BufferPoolAllocator> &allocator)
- : mAllocator(allocator), mScheduleEvictTs(0) {}
-
-Accessor::Impl::~Impl() {
-}
-
-ResultStatus Accessor::Impl::connect(
- const sp<Accessor> &accessor, const sp<IObserver> &observer,
- sp<Connection> *connection,
- ConnectionId *pConnectionId,
- uint32_t *pMsgId,
- const StatusDescriptor** statusDescPtr,
- const InvalidationDescriptor** invDescPtr) {
- sp<Connection> newConnection = new Connection();
- ResultStatus status = ResultStatus::CRITICAL_ERROR;
- {
- std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
- if (newConnection) {
- int32_t pid = getpid();
- ConnectionId id = (int64_t)pid << 32 | sSeqId | kSeqIdVndkBit;
- status = mBufferPool.mObserver.open(id, statusDescPtr);
- if (status == ResultStatus::OK) {
- newConnection->initialize(accessor, id);
- *connection = newConnection;
- *pConnectionId = id;
- *pMsgId = mBufferPool.mInvalidation.mInvalidationId;
- mBufferPool.mConnectionIds.insert(id);
- mBufferPool.mInvalidationChannel.getDesc(invDescPtr);
- mBufferPool.mInvalidation.onConnect(id, observer);
- if (sSeqId == kSeqIdMax) {
- sSeqId = 0;
- } else {
- ++sSeqId;
- }
- }
-
- }
- mBufferPool.processStatusMessages();
- mBufferPool.cleanUp();
- scheduleEvictIfNeeded();
- }
- return status;
-}
-
-ResultStatus Accessor::Impl::close(ConnectionId connectionId) {
- std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
- ALOGV("connection close %lld: %u", (long long)connectionId, mBufferPool.mInvalidation.mId);
- mBufferPool.processStatusMessages();
- mBufferPool.handleClose(connectionId);
- mBufferPool.mObserver.close(connectionId);
- mBufferPool.mInvalidation.onClose(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;
-}
-
-ResultStatus Accessor::Impl::allocate(
- ConnectionId connectionId, const std::vector<uint8_t>& params,
- BufferId *bufferId, const native_handle_t** handle) {
- std::unique_lock<std::mutex> lock(mBufferPool.mMutex);
- mBufferPool.processStatusMessages();
- ResultStatus status = ResultStatus::OK;
- if (!mBufferPool.getFreeBuffer(mAllocator, params, bufferId, handle)) {
- lock.unlock();
- std::shared_ptr<BufferPoolAllocation> alloc;
- size_t allocSize;
- status = mAllocator->allocate(params, &alloc, &allocSize);
- lock.lock();
- if (status == ResultStatus::OK) {
- status = mBufferPool.addNewBuffer(alloc, allocSize, params, bufferId, handle);
- }
- ALOGV("create a buffer %d : %u %p",
- status == ResultStatus::OK, *bufferId, *handle);
- }
- if (status == ResultStatus::OK) {
- // TODO: handle ownBuffer failure
- mBufferPool.handleOwnBuffer(connectionId, *bufferId);
- }
- mBufferPool.cleanUp();
- scheduleEvictIfNeeded();
- return status;
-}
-
-ResultStatus Accessor::Impl::fetch(
- ConnectionId connectionId, TransactionId transactionId,
- BufferId bufferId, const native_handle_t** handle) {
- std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
- mBufferPool.processStatusMessages();
- auto found = mBufferPool.mTransactions.find(transactionId);
- if (found != mBufferPool.mTransactions.end() &&
- contains(&mBufferPool.mPendingTransactions,
- connectionId, transactionId)) {
- if (found->second->mSenderValidated &&
- found->second->mStatus == BufferStatus::TRANSFER_FROM &&
- found->second->mBufferId == bufferId) {
- found->second->mStatus = BufferStatus::TRANSFER_FETCH;
- auto bufferIt = mBufferPool.mBuffers.find(bufferId);
- if (bufferIt != mBufferPool.mBuffers.end()) {
- mBufferPool.mStats.onBufferFetched();
- *handle = bufferIt->second->handle();
- return ResultStatus::OK;
- }
- }
- }
- mBufferPool.cleanUp();
- scheduleEvictIfNeeded();
- return ResultStatus::CRITICAL_ERROR;
-}
-
-void Accessor::Impl::cleanUp(bool clearCache) {
- // transaction timeout, buffer cacheing TTL handling
- std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
- mBufferPool.processStatusMessages();
- mBufferPool.cleanUp(clearCache);
-}
-
-void Accessor::Impl::flush() {
- std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
- mBufferPool.processStatusMessages();
- mBufferPool.flush(shared_from_this());
-}
-
-void Accessor::Impl::handleInvalidateAck() {
- std::map<ConnectionId, const sp<IObserver>> observers;
- uint32_t invalidationId;
- {
- std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
- mBufferPool.processStatusMessages();
- mBufferPool.mInvalidation.onHandleAck(&observers, &invalidationId);
- }
- // Do not hold lock for send invalidations
- size_t deadClients = 0;
- for (auto it = observers.begin(); it != observers.end(); ++it) {
- const sp<IObserver> observer = it->second;
- if (observer) {
- Return<void> transResult = observer->onMessage(it->first, invalidationId);
- if (!transResult.isOk()) {
- ++deadClients;
- }
- }
- }
- if (deadClients > 0) {
- ALOGD("During invalidation found %zu dead clients", deadClients);
- }
-}
-
-bool Accessor::Impl::isValid() {
- return mBufferPool.isValid();
-}
-
-Accessor::Impl::Impl::BufferPool::BufferPool()
- : mTimestampUs(getTimestampNow()),
- mLastCleanUpUs(mTimestampUs),
- mLastLogUs(mTimestampUs),
- mSeq(0),
- mStartSeq(0) {
- mValid = mInvalidationChannel.isValid();
-}
-
-
-// Statistics helper
-template<typename T, typename S>
-int percentage(T base, S total) {
- return int(total ? 0.5 + 100. * static_cast<S>(base) / total : 0);
-}
-
-std::atomic<std::uint32_t> Accessor::Impl::BufferPool::Invalidation::sInvSeqId(0);
-
-Accessor::Impl::Impl::BufferPool::~BufferPool() {
- std::lock_guard<std::mutex> lock(mMutex);
- ALOGD("Destruction - bufferpool2 %p "
- "cached: %zu/%zuM, %zu/%d%% in use; "
- "allocs: %zu, %d%% recycled; "
- "transfers: %zu, %d%% unfetched",
- this, mStats.mBuffersCached, mStats.mSizeCached >> 20,
- mStats.mBuffersInUse, percentage(mStats.mBuffersInUse, mStats.mBuffersCached),
- mStats.mTotalAllocations, percentage(mStats.mTotalRecycles, mStats.mTotalAllocations),
- mStats.mTotalTransfers,
- percentage(mStats.mTotalTransfers - mStats.mTotalFetches, mStats.mTotalTransfers));
-}
-
-void Accessor::Impl::BufferPool::Invalidation::onConnect(
- ConnectionId conId, const sp<IObserver>& observer) {
- mAcks[conId] = mInvalidationId; // starts from current invalidationId
- mObservers.insert(std::make_pair(conId, observer));
-}
-
-void Accessor::Impl::BufferPool::Invalidation::onClose(ConnectionId conId) {
- mAcks.erase(conId);
- mObservers.erase(conId);
-}
-
-void Accessor::Impl::BufferPool::Invalidation::onAck(
- ConnectionId conId,
- uint32_t msgId) {
- auto it = mAcks.find(conId);
- if (it == mAcks.end()) {
- ALOGW("ACK from inconsistent connection! %lld", (long long)conId);
- return;
- }
- if (isMessageLater(msgId, it->second)) {
- mAcks[conId] = msgId;
- }
-}
-
-void Accessor::Impl::BufferPool::Invalidation::onBufferInvalidated(
- BufferId bufferId,
- BufferInvalidationChannel &channel) {
- for (auto it = mPendings.begin(); it != mPendings.end();) {
- if (it->isInvalidated(bufferId)) {
- uint32_t msgId = 0;
- if (it->mNeedsAck) {
- msgId = ++mInvalidationId;
- if (msgId == 0) {
- // wrap happens
- msgId = ++mInvalidationId;
- }
- }
- channel.postInvalidation(msgId, it->mFrom, it->mTo);
- it = mPendings.erase(it);
- continue;
- }
- ++it;
- }
-}
-
-void Accessor::Impl::BufferPool::Invalidation::onInvalidationRequest(
- bool needsAck,
- uint32_t from,
- uint32_t to,
- size_t left,
- BufferInvalidationChannel &channel,
- const std::shared_ptr<Accessor::Impl> &impl) {
- uint32_t msgId = 0;
- if (needsAck) {
- msgId = ++mInvalidationId;
- if (msgId == 0) {
- // wrap happens
- msgId = ++mInvalidationId;
- }
- }
- ALOGV("bufferpool2 invalidation requested and queued");
- if (left == 0) {
- channel.postInvalidation(msgId, from, to);
- } else {
- // TODO: sending hint message?
- ALOGV("bufferpoo2 invalidation requested and pending");
- Pending pending(needsAck, from, to, left, impl);
- mPendings.push_back(pending);
- }
- sInvalidator->addAccessor(mId, impl);
-}
-
-void Accessor::Impl::BufferPool::Invalidation::onHandleAck(
- std::map<ConnectionId, const sp<IObserver>> *observers,
- uint32_t *invalidationId) {
- if (mInvalidationId != 0) {
- *invalidationId = mInvalidationId;
- std::set<int> deads;
- for (auto it = mAcks.begin(); it != mAcks.end(); ++it) {
- if (it->second != mInvalidationId) {
- const sp<IObserver> observer = mObservers[it->first];
- if (observer) {
- observers->emplace(it->first, observer);
- ALOGV("connection %lld will call observer (%u: %u)",
- (long long)it->first, it->second, mInvalidationId);
- // N.B: onMessage will be called later. ignore possibility of
- // onMessage# oneway call being lost.
- it->second = mInvalidationId;
- } else {
- ALOGV("bufferpool2 observer died %lld", (long long)it->first);
- deads.insert(it->first);
- }
- }
- }
- if (deads.size() > 0) {
- for (auto it = deads.begin(); it != deads.end(); ++it) {
- onClose(*it);
- }
- }
- }
- if (mPendings.size() == 0) {
- // All invalidation Ids are synced and no more pending invalidations.
- sInvalidator->delAccessor(mId);
- }
-}
-
-bool Accessor::Impl::BufferPool::handleOwnBuffer(
- ConnectionId connectionId, BufferId bufferId) {
-
- bool added = insert(&mUsingBuffers, connectionId, bufferId);
- if (added) {
- auto iter = mBuffers.find(bufferId);
- iter->second->mOwnerCount++;
- }
- insert(&mUsingConnections, bufferId, connectionId);
- return added;
-}
-
-bool Accessor::Impl::BufferPool::handleReleaseBuffer(
- ConnectionId connectionId, BufferId bufferId) {
- bool deleted = erase(&mUsingBuffers, connectionId, bufferId);
- if (deleted) {
- auto iter = mBuffers.find(bufferId);
- iter->second->mOwnerCount--;
- if (iter->second->mOwnerCount == 0 &&
- iter->second->mTransactionCount == 0) {
- if (!iter->second->mInvalidated) {
- mStats.onBufferUnused(iter->second->mAllocSize);
- mFreeBuffers.insert(bufferId);
- } else {
- mStats.onBufferUnused(iter->second->mAllocSize);
- mStats.onBufferEvicted(iter->second->mAllocSize);
- mBuffers.erase(iter);
- mInvalidation.onBufferInvalidated(bufferId, mInvalidationChannel);
- }
- }
- }
- erase(&mUsingConnections, bufferId, connectionId);
- ALOGV("release buffer %u : %d", bufferId, deleted);
- return deleted;
-}
-
-bool Accessor::Impl::BufferPool::handleTransferTo(const BufferStatusMessage &message) {
- auto completed = mCompletedTransactions.find(
- message.transactionId);
- if (completed != mCompletedTransactions.end()) {
- // already completed
- mCompletedTransactions.erase(completed);
- return true;
- }
- // the buffer should exist and be owned.
- auto bufferIter = mBuffers.find(message.bufferId);
- if (bufferIter == mBuffers.end() ||
- !contains(&mUsingBuffers, message.connectionId, message.bufferId)) {
- return false;
- }
- auto found = mTransactions.find(message.transactionId);
- if (found != mTransactions.end()) {
- // transfer_from was received earlier.
- found->second->mSender = message.connectionId;
- found->second->mSenderValidated = true;
- return true;
- }
- if (mConnectionIds.find(message.targetConnectionId) == mConnectionIds.end()) {
- // N.B: it could be fake or receive connection already closed.
- ALOGD("bufferpool2 %p receiver connection %lld is no longer valid",
- this, (long long)message.targetConnectionId);
- return false;
- }
- mStats.onBufferSent();
- mTransactions.insert(std::make_pair(
- message.transactionId,
- std::make_unique<TransactionStatus>(message, mTimestampUs)));
- insert(&mPendingTransactions, message.targetConnectionId,
- message.transactionId);
- bufferIter->second->mTransactionCount++;
- return true;
-}
-
-bool Accessor::Impl::BufferPool::handleTransferFrom(const BufferStatusMessage &message) {
- auto found = mTransactions.find(message.transactionId);
- if (found == mTransactions.end()) {
- // TODO: is it feasible to check ownership here?
- mStats.onBufferSent();
- mTransactions.insert(std::make_pair(
- message.transactionId,
- std::make_unique<TransactionStatus>(message, mTimestampUs)));
- insert(&mPendingTransactions, message.connectionId,
- message.transactionId);
- auto bufferIter = mBuffers.find(message.bufferId);
- bufferIter->second->mTransactionCount++;
- } else {
- if (message.connectionId == found->second->mReceiver) {
- found->second->mStatus = BufferStatus::TRANSFER_FROM;
- }
- }
- return true;
-}
-
-bool Accessor::Impl::BufferPool::handleTransferResult(const BufferStatusMessage &message) {
- auto found = mTransactions.find(message.transactionId);
- if (found != mTransactions.end()) {
- bool deleted = erase(&mPendingTransactions, message.connectionId,
- message.transactionId);
- if (deleted) {
- if (!found->second->mSenderValidated) {
- mCompletedTransactions.insert(message.transactionId);
- }
- auto bufferIter = mBuffers.find(message.bufferId);
- if (message.newStatus == BufferStatus::TRANSFER_OK) {
- handleOwnBuffer(message.connectionId, message.bufferId);
- }
- bufferIter->second->mTransactionCount--;
- if (bufferIter->second->mOwnerCount == 0
- && bufferIter->second->mTransactionCount == 0) {
- if (!bufferIter->second->mInvalidated) {
- mStats.onBufferUnused(bufferIter->second->mAllocSize);
- mFreeBuffers.insert(message.bufferId);
- } else {
- mStats.onBufferUnused(bufferIter->second->mAllocSize);
- mStats.onBufferEvicted(bufferIter->second->mAllocSize);
- mBuffers.erase(bufferIter);
- mInvalidation.onBufferInvalidated(message.bufferId, mInvalidationChannel);
- }
- }
- mTransactions.erase(found);
- }
- ALOGV("transfer finished %llu %u - %d", (unsigned long long)message.transactionId,
- message.bufferId, deleted);
- return deleted;
- }
- ALOGV("transfer not found %llu %u", (unsigned long long)message.transactionId,
- message.bufferId);
- return false;
-}
-
-void Accessor::Impl::BufferPool::processStatusMessages() {
- std::vector<BufferStatusMessage> messages;
- mObserver.getBufferStatusChanges(messages);
- mTimestampUs = getTimestampNow();
- for (BufferStatusMessage& message: messages) {
- bool ret = false;
- switch (message.newStatus) {
- case BufferStatus::NOT_USED:
- ret = handleReleaseBuffer(
- message.connectionId, message.bufferId);
- break;
- case BufferStatus::USED:
- // not happening
- break;
- case BufferStatus::TRANSFER_TO:
- ret = handleTransferTo(message);
- break;
- case BufferStatus::TRANSFER_FROM:
- ret = handleTransferFrom(message);
- break;
- case BufferStatus::TRANSFER_TIMEOUT:
- // TODO
- break;
- case BufferStatus::TRANSFER_LOST:
- // TODO
- break;
- case BufferStatus::TRANSFER_FETCH:
- // not happening
- break;
- case BufferStatus::TRANSFER_OK:
- case BufferStatus::TRANSFER_ERROR:
- ret = handleTransferResult(message);
- break;
- case BufferStatus::INVALIDATION_ACK:
- mInvalidation.onAck(message.connectionId, message.bufferId);
- ret = true;
- break;
- }
- if (ret == false) {
- ALOGW("buffer status message processing failure - message : %d connection : %lld",
- message.newStatus, (long long)message.connectionId);
- }
- }
- messages.clear();
-}
-
-bool Accessor::Impl::BufferPool::handleClose(ConnectionId connectionId) {
- // Cleaning buffers
- auto buffers = mUsingBuffers.find(connectionId);
- if (buffers != mUsingBuffers.end()) {
- for (const BufferId& bufferId : buffers->second) {
- bool deleted = erase(&mUsingConnections, bufferId, connectionId);
- if (deleted) {
- auto bufferIter = mBuffers.find(bufferId);
- bufferIter->second->mOwnerCount--;
- if (bufferIter->second->mOwnerCount == 0 &&
- bufferIter->second->mTransactionCount == 0) {
- // TODO: handle freebuffer insert fail
- if (!bufferIter->second->mInvalidated) {
- mStats.onBufferUnused(bufferIter->second->mAllocSize);
- mFreeBuffers.insert(bufferId);
- } else {
- mStats.onBufferUnused(bufferIter->second->mAllocSize);
- mStats.onBufferEvicted(bufferIter->second->mAllocSize);
- mBuffers.erase(bufferIter);
- mInvalidation.onBufferInvalidated(bufferId, mInvalidationChannel);
- }
- }
- }
- }
- mUsingBuffers.erase(buffers);
- }
-
- // Cleaning transactions
- auto pending = mPendingTransactions.find(connectionId);
- if (pending != mPendingTransactions.end()) {
- for (const TransactionId& transactionId : pending->second) {
- auto iter = mTransactions.find(transactionId);
- if (iter != mTransactions.end()) {
- if (!iter->second->mSenderValidated) {
- mCompletedTransactions.insert(transactionId);
- }
- BufferId bufferId = iter->second->mBufferId;
- auto bufferIter = mBuffers.find(bufferId);
- bufferIter->second->mTransactionCount--;
- if (bufferIter->second->mOwnerCount == 0 &&
- bufferIter->second->mTransactionCount == 0) {
- // TODO: handle freebuffer insert fail
- if (!bufferIter->second->mInvalidated) {
- mStats.onBufferUnused(bufferIter->second->mAllocSize);
- mFreeBuffers.insert(bufferId);
- } else {
- mStats.onBufferUnused(bufferIter->second->mAllocSize);
- mStats.onBufferEvicted(bufferIter->second->mAllocSize);
- mBuffers.erase(bufferIter);
- mInvalidation.onBufferInvalidated(bufferId, mInvalidationChannel);
- }
- }
- mTransactions.erase(iter);
- }
- }
- }
- mConnectionIds.erase(connectionId);
- return true;
-}
-
-bool Accessor::Impl::BufferPool::getFreeBuffer(
- const std::shared_ptr<BufferPoolAllocator> &allocator,
- const std::vector<uint8_t> ¶ms, BufferId *pId,
- const native_handle_t** handle) {
- auto bufferIt = mFreeBuffers.begin();
- for (;bufferIt != mFreeBuffers.end(); ++bufferIt) {
- BufferId bufferId = *bufferIt;
- if (allocator->compatible(params, mBuffers[bufferId]->mConfig)) {
- break;
- }
- }
- if (bufferIt != mFreeBuffers.end()) {
- BufferId id = *bufferIt;
- mFreeBuffers.erase(bufferIt);
- mStats.onBufferRecycled(mBuffers[id]->mAllocSize);
- *handle = mBuffers[id]->handle();
- *pId = id;
- ALOGV("recycle a buffer %u %p", id, *handle);
- return true;
- }
- return false;
-}
-
-ResultStatus Accessor::Impl::BufferPool::addNewBuffer(
- const std::shared_ptr<BufferPoolAllocation> &alloc,
- const size_t allocSize,
- const std::vector<uint8_t> ¶ms,
- BufferId *pId,
- const native_handle_t** handle) {
-
- BufferId bufferId = mSeq++;
- if (mSeq == Connection::SYNC_BUFFERID) {
- mSeq = 0;
- }
- std::unique_ptr<InternalBuffer> buffer =
- std::make_unique<InternalBuffer>(
- bufferId, alloc, allocSize, params);
- if (buffer) {
- auto res = mBuffers.insert(std::make_pair(
- bufferId, std::move(buffer)));
- if (res.second) {
- mStats.onBufferAllocated(allocSize);
- *handle = alloc->handle();
- *pId = bufferId;
- return ResultStatus::OK;
- }
- }
- return ResultStatus::NO_MEMORY;
-}
-
-void Accessor::Impl::BufferPool::cleanUp(bool clearCache) {
- if (clearCache || mTimestampUs > mLastCleanUpUs + kCleanUpDurationUs ||
- mStats.buffersNotInUse() > kMaxUnusedBufferCount) {
- mLastCleanUpUs = mTimestampUs;
- if (mTimestampUs > mLastLogUs + kLogDurationUs ||
- mStats.buffersNotInUse() > kMaxUnusedBufferCount) {
- mLastLogUs = mTimestampUs;
- ALOGD("bufferpool2 %p : %zu(%zu size) total buffers - "
- "%zu(%zu size) used buffers - %zu/%zu (recycle/alloc) - "
- "%zu/%zu (fetch/transfer)",
- this, mStats.mBuffersCached, mStats.mSizeCached,
- mStats.mBuffersInUse, mStats.mSizeInUse,
- mStats.mTotalRecycles, mStats.mTotalAllocations,
- mStats.mTotalFetches, mStats.mTotalTransfers);
- }
- for (auto freeIt = mFreeBuffers.begin(); freeIt != mFreeBuffers.end();) {
- if (!clearCache && mStats.buffersNotInUse() <= kUnusedBufferCountTarget &&
- (mStats.mSizeCached < kMinAllocBytesForEviction ||
- mBuffers.size() < kMinBufferCountForEviction)) {
- break;
- }
- auto it = mBuffers.find(*freeIt);
- if (it != mBuffers.end() &&
- it->second->mOwnerCount == 0 && it->second->mTransactionCount == 0) {
- mStats.onBufferEvicted(it->second->mAllocSize);
- mBuffers.erase(it);
- freeIt = mFreeBuffers.erase(freeIt);
- } else {
- ++freeIt;
- ALOGW("bufferpool2 inconsistent!");
- }
- }
- }
-}
-
-void Accessor::Impl::BufferPool::invalidate(
- bool needsAck, BufferId from, BufferId to,
- const std::shared_ptr<Accessor::Impl> &impl) {
- for (auto freeIt = mFreeBuffers.begin(); freeIt != mFreeBuffers.end();) {
- if (isBufferInRange(from, to, *freeIt)) {
- auto it = mBuffers.find(*freeIt);
- if (it != mBuffers.end() &&
- it->second->mOwnerCount == 0 && it->second->mTransactionCount == 0) {
- mStats.onBufferEvicted(it->second->mAllocSize);
- mBuffers.erase(it);
- freeIt = mFreeBuffers.erase(freeIt);
- continue;
- } else {
- ALOGW("bufferpool2 inconsistent!");
- }
- }
- ++freeIt;
- }
-
- size_t left = 0;
- for (auto it = mBuffers.begin(); it != mBuffers.end(); ++it) {
- if (isBufferInRange(from, to, it->first)) {
- it->second->invalidate();
- ++left;
- }
- }
- mInvalidation.onInvalidationRequest(needsAck, from, to, left, mInvalidationChannel, impl);
-}
-
-void Accessor::Impl::BufferPool::flush(const std::shared_ptr<Accessor::Impl> &impl) {
- BufferId from = mStartSeq;
- BufferId to = mSeq;
- mStartSeq = mSeq;
- // TODO: needsAck params
- ALOGV("buffer invalidation request bp:%u %u %u", mInvalidation.mId, from, to);
- if (from != to) {
- invalidate(true, from, to, impl);
- }
-}
-
-void Accessor::Impl::invalidatorThread(
- std::map<uint32_t, const std::weak_ptr<Accessor::Impl>> &accessors,
- std::mutex &mutex,
- std::condition_variable &cv,
- bool &ready) {
- constexpr uint32_t NUM_SPIN_TO_INCREASE_SLEEP = 1024;
- constexpr uint32_t NUM_SPIN_TO_LOG = 1024*8;
- constexpr useconds_t MAX_SLEEP_US = 10000;
- uint32_t numSpin = 0;
- useconds_t sleepUs = 1;
-
- while(true) {
- std::map<uint32_t, const std::weak_ptr<Accessor::Impl>> copied;
- {
- std::unique_lock<std::mutex> lock(mutex);
- if (!ready) {
- numSpin = 0;
- sleepUs = 1;
- cv.wait(lock);
- }
- copied.insert(accessors.begin(), accessors.end());
- }
- std::list<ConnectionId> erased;
- for (auto it = copied.begin(); it != copied.end(); ++it) {
- const std::shared_ptr<Accessor::Impl> impl = it->second.lock();
- if (!impl) {
- erased.push_back(it->first);
- } else {
- impl->handleInvalidateAck();
- }
- }
- {
- std::unique_lock<std::mutex> lock(mutex);
- for (auto it = erased.begin(); it != erased.end(); ++it) {
- accessors.erase(*it);
- }
- if (accessors.size() == 0) {
- ready = false;
- } else {
- // TODO Use an efficient way to wait over FMQ.
- // N.B. Since there is not a efficient way to wait over FMQ,
- // polling over the FMQ is the current way to prevent draining
- // CPU.
- lock.unlock();
- ++numSpin;
- if (numSpin % NUM_SPIN_TO_INCREASE_SLEEP == 0 &&
- sleepUs < MAX_SLEEP_US) {
- sleepUs *= 10;
- }
- if (numSpin % NUM_SPIN_TO_LOG == 0) {
- ALOGW("invalidator thread spinning");
- }
- ::usleep(sleepUs);
- }
- }
- }
-}
-
-Accessor::Impl::AccessorInvalidator::AccessorInvalidator() : mReady(false) {
- std::thread invalidator(
- invalidatorThread,
- std::ref(mAccessors),
- std::ref(mMutex),
- std::ref(mCv),
- std::ref(mReady));
- invalidator.detach();
-}
-
-void Accessor::Impl::AccessorInvalidator::addAccessor(
- uint32_t accessorId, const std::weak_ptr<Accessor::Impl> &impl) {
- bool notify = false;
- std::unique_lock<std::mutex> lock(mMutex);
- if (mAccessors.find(accessorId) == mAccessors.end()) {
- if (!mReady) {
- mReady = true;
- notify = true;
- }
- mAccessors.insert(std::make_pair(accessorId, impl));
- ALOGV("buffer invalidation added bp:%u %d", accessorId, notify);
- }
- lock.unlock();
- if (notify) {
- mCv.notify_one();
- }
-}
-
-void Accessor::Impl::AccessorInvalidator::delAccessor(uint32_t accessorId) {
- std::lock_guard<std::mutex> lock(mMutex);
- mAccessors.erase(accessorId);
- ALOGV("buffer invalidation deleted bp:%u", accessorId);
- if (mAccessors.size() == 0) {
- mReady = false;
- }
-}
-
-std::unique_ptr<Accessor::Impl::AccessorInvalidator> Accessor::Impl::sInvalidator;
-
-void Accessor::Impl::createInvalidator() {
- if (!sInvalidator) {
- sInvalidator = std::make_unique<Accessor::Impl::AccessorInvalidator>();
- }
-}
-
-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
-} // namespace media
-} // namespace hardware
-} // namespace android
diff --git a/media/bufferpool/aidl/default/AccessorImpl.h b/media/bufferpool/aidl/default/AccessorImpl.h
deleted file mode 100644
index 3d39941..0000000
--- a/media/bufferpool/aidl/default/AccessorImpl.h
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_ACCESSORIMPL_H
-#define ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_ACCESSORIMPL_H
-
-#include <map>
-#include <set>
-#include <condition_variable>
-#include <utils/Timers.h>
-#include "Accessor.h"
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
-namespace V2_0 {
-namespace implementation {
-
-struct InternalBuffer;
-struct TransactionStatus;
-
-/**
- * An implementation of a buffer pool accessor(or a buffer pool implementation.) */
-class Accessor::Impl
- : public std::enable_shared_from_this<Accessor::Impl> {
-public:
- Impl(const std::shared_ptr<BufferPoolAllocator> &allocator);
-
- ~Impl();
-
- ResultStatus connect(
- const sp<Accessor> &accessor, const sp<IObserver> &observer,
- sp<Connection> *connection,
- ConnectionId *pConnectionId,
- uint32_t *pMsgId,
- const StatusDescriptor** statusDescPtr,
- const InvalidationDescriptor** invDescPtr);
-
- ResultStatus close(ConnectionId connectionId);
-
- ResultStatus allocate(ConnectionId connectionId,
- const std::vector<uint8_t>& params,
- BufferId *bufferId,
- const native_handle_t** handle);
-
- ResultStatus fetch(ConnectionId connectionId,
- TransactionId transactionId,
- BufferId bufferId,
- const native_handle_t** handle);
-
- void flush();
-
- void cleanUp(bool clearCache);
-
- bool isValid();
-
- void handleInvalidateAck();
-
- static void createInvalidator();
-
- static void createEvictor();
-
-private:
- // ConnectionId = pid : (timestamp_created + seqId)
- // in order to guarantee uniqueness for each connection
- static uint32_t sSeqId;
-
- const std::shared_ptr<BufferPoolAllocator> mAllocator;
-
- nsecs_t mScheduleEvictTs;
-
- /**
- * Buffer pool implementation.
- *
- * Handles buffer status messages. Handles buffer allocation/recycling.
- * Handles buffer transfer between buffer pool clients.
- */
- struct BufferPool {
- private:
- std::mutex mMutex;
- int64_t mTimestampUs;
- int64_t mLastCleanUpUs;
- int64_t mLastLogUs;
- BufferId mSeq;
- BufferId mStartSeq;
- bool mValid;
- BufferStatusObserver mObserver;
- BufferInvalidationChannel mInvalidationChannel;
-
- std::map<ConnectionId, std::set<BufferId>> mUsingBuffers;
- std::map<BufferId, std::set<ConnectionId>> mUsingConnections;
-
- std::map<ConnectionId, std::set<TransactionId>> mPendingTransactions;
- // Transactions completed before TRANSFER_TO message arrival.
- // Fetch does not occur for the transactions.
- // Only transaction id is kept for the transactions in short duration.
- std::set<TransactionId> mCompletedTransactions;
- // Currently active(pending) transations' status & information.
- std::map<TransactionId, std::unique_ptr<TransactionStatus>>
- mTransactions;
-
- std::map<BufferId, std::unique_ptr<InternalBuffer>> mBuffers;
- std::set<BufferId> mFreeBuffers;
- std::set<ConnectionId> mConnectionIds;
-
- struct Invalidation {
- static std::atomic<std::uint32_t> sInvSeqId;
-
- struct Pending {
- bool mNeedsAck;
- uint32_t mFrom;
- uint32_t mTo;
- size_t mLeft;
- const std::weak_ptr<Accessor::Impl> mImpl;
- Pending(bool needsAck, uint32_t from, uint32_t to, size_t left,
- const std::shared_ptr<Accessor::Impl> &impl)
- : mNeedsAck(needsAck),
- mFrom(from),
- mTo(to),
- mLeft(left),
- mImpl(impl)
- {}
-
- bool isInvalidated(uint32_t bufferId) {
- return isBufferInRange(mFrom, mTo, bufferId) && --mLeft == 0;
- }
- };
-
- std::list<Pending> mPendings;
- std::map<ConnectionId, uint32_t> mAcks;
- std::map<ConnectionId, const sp<IObserver>> mObservers;
- uint32_t mInvalidationId;
- uint32_t mId;
-
- Invalidation() : mInvalidationId(0), mId(sInvSeqId.fetch_add(1)) {}
-
- void onConnect(ConnectionId conId, const sp<IObserver> &observer);
-
- void onClose(ConnectionId conId);
-
- void onAck(ConnectionId conId, uint32_t msgId);
-
- void onBufferInvalidated(
- BufferId bufferId,
- BufferInvalidationChannel &channel);
-
- void onInvalidationRequest(
- bool needsAck, uint32_t from, uint32_t to, size_t left,
- BufferInvalidationChannel &channel,
- const std::shared_ptr<Accessor::Impl> &impl);
-
- void onHandleAck(
- std::map<ConnectionId, const sp<IObserver>> *observers,
- uint32_t *invalidationId);
- } mInvalidation;
- /// Buffer pool statistics which tracks allocation and transfer statistics.
- struct Stats {
- /// Total size of allocations which are used or available to use.
- /// (bytes or pixels)
- size_t mSizeCached;
- /// # of cached buffers which are used or available to use.
- size_t mBuffersCached;
- /// Total size of allocations which are currently used. (bytes or pixels)
- size_t mSizeInUse;
- /// # of currently used buffers
- size_t mBuffersInUse;
-
- /// # of allocations called on bufferpool. (# of fetched from BlockPool)
- size_t mTotalAllocations;
- /// # of allocations that were served from the cache.
- /// (# of allocator alloc prevented)
- size_t mTotalRecycles;
- /// # of buffer transfers initiated.
- size_t mTotalTransfers;
- /// # of transfers that had to be fetched.
- size_t mTotalFetches;
-
- Stats()
- : mSizeCached(0), mBuffersCached(0), mSizeInUse(0), mBuffersInUse(0),
- mTotalAllocations(0), mTotalRecycles(0), mTotalTransfers(0), mTotalFetches(0) {}
-
- /// # of currently unused buffers
- size_t buffersNotInUse() const {
- ALOG_ASSERT(mBuffersCached >= mBuffersInUse);
- return mBuffersCached - mBuffersInUse;
- }
-
- /// A new buffer is allocated on an allocation request.
- void onBufferAllocated(size_t allocSize) {
- mSizeCached += allocSize;
- mBuffersCached++;
-
- mSizeInUse += allocSize;
- mBuffersInUse++;
-
- mTotalAllocations++;
- }
-
- /// A buffer is evicted and destroyed.
- void onBufferEvicted(size_t allocSize) {
- mSizeCached -= allocSize;
- mBuffersCached--;
- }
-
- /// A buffer is recycled on an allocation request.
- void onBufferRecycled(size_t allocSize) {
- mSizeInUse += allocSize;
- mBuffersInUse++;
-
- mTotalAllocations++;
- mTotalRecycles++;
- }
-
- /// A buffer is available to be recycled.
- void onBufferUnused(size_t allocSize) {
- mSizeInUse -= allocSize;
- mBuffersInUse--;
- }
-
- /// A buffer transfer is initiated.
- void onBufferSent() {
- mTotalTransfers++;
- }
-
- /// A buffer fetch is invoked by a buffer transfer.
- void onBufferFetched() {
- mTotalFetches++;
- }
- } mStats;
-
- bool isValid() {
- return mValid;
- }
-
- void invalidate(bool needsAck, BufferId from, BufferId to,
- const std::shared_ptr<Accessor::Impl> &impl);
-
- static void createInvalidator();
-
- public:
- /** Creates a buffer pool. */
- BufferPool();
-
- /** Destroys a buffer pool. */
- ~BufferPool();
-
- /**
- * Processes all pending buffer status messages, and returns the result.
- * Each status message is handled by methods with 'handle' prefix.
- */
- void processStatusMessages();
-
- /**
- * Handles a buffer being owned by a connection.
- *
- * @param connectionId the id of the buffer owning connection.
- * @param bufferId the id of the buffer.
- *
- * @return {@code true} when the buffer is owned,
- * {@code false} otherwise.
- */
- bool handleOwnBuffer(ConnectionId connectionId, BufferId bufferId);
-
- /**
- * Handles a buffer being released by a connection.
- *
- * @param connectionId the id of the buffer owning connection.
- * @param bufferId the id of the buffer.
- *
- * @return {@code true} when the buffer ownership is released,
- * {@code false} otherwise.
- */
- bool handleReleaseBuffer(ConnectionId connectionId, BufferId bufferId);
-
- /**
- * Handles a transfer transaction start message from the sender.
- *
- * @param message a buffer status message for the transaction.
- *
- * @result {@code true} when transfer_to message is acknowledged,
- * {@code false} otherwise.
- */
- bool handleTransferTo(const BufferStatusMessage &message);
-
- /**
- * Handles a transfer transaction being acked by the receiver.
- *
- * @param message a buffer status message for the transaction.
- *
- * @result {@code true} when transfer_from message is acknowledged,
- * {@code false} otherwise.
- */
- bool handleTransferFrom(const BufferStatusMessage &message);
-
- /**
- * Handles a transfer transaction result message from the receiver.
- *
- * @param message a buffer status message for the transaction.
- *
- * @result {@code true} when the exisitng transaction is finished,
- * {@code false} otherwise.
- */
- bool handleTransferResult(const BufferStatusMessage &message);
-
- /**
- * Handles a connection being closed, and returns the result. All the
- * buffers and transactions owned by the connection will be cleaned up.
- * The related FMQ will be cleaned up too.
- *
- * @param connectionId the id of the connection.
- *
- * @result {@code true} when the connection existed,
- * {@code false} otherwise.
- */
- bool handleClose(ConnectionId connectionId);
-
- /**
- * Recycles a existing free buffer if it is possible.
- *
- * @param allocator the buffer allocator
- * @param params the allocation parameters.
- * @param pId the id of the recycled buffer.
- * @param handle the native handle of the recycled buffer.
- *
- * @return {@code true} when a buffer is recycled, {@code false}
- * otherwise.
- */
- bool getFreeBuffer(
- const std::shared_ptr<BufferPoolAllocator> &allocator,
- const std::vector<uint8_t> ¶ms,
- BufferId *pId, const native_handle_t **handle);
-
- /**
- * Adds a newly allocated buffer to bufferpool.
- *
- * @param alloc the newly allocated buffer.
- * @param allocSize the size of the newly allocated buffer.
- * @param params the allocation parameters.
- * @param pId the buffer id for the newly allocated buffer.
- * @param handle the native handle for the newly allocated buffer.
- *
- * @return OK when an allocation is successfully allocated.
- * NO_MEMORY when there is no memory.
- * CRITICAL_ERROR otherwise.
- */
- ResultStatus addNewBuffer(
- const std::shared_ptr<BufferPoolAllocation> &alloc,
- const size_t allocSize,
- const std::vector<uint8_t> ¶ms,
- BufferId *pId,
- const native_handle_t **handle);
-
- /**
- * Processes pending buffer status messages and performs periodic cache
- * cleaning.
- *
- * @param clearCache if clearCache is true, it frees all buffers
- * waiting to be recycled.
- */
- void cleanUp(bool clearCache = false);
-
- /**
- * Processes pending buffer status messages and invalidate all current
- * free buffers. Active buffers are invalidated after being inactive.
- */
- void flush(const std::shared_ptr<Accessor::Impl> &impl);
-
- friend class Accessor::Impl;
- } mBufferPool;
-
- struct AccessorInvalidator {
- std::map<uint32_t, const std::weak_ptr<Accessor::Impl>> mAccessors;
- std::mutex mMutex;
- std::condition_variable mCv;
- bool mReady;
-
- AccessorInvalidator();
- void addAccessor(uint32_t accessorId, const std::weak_ptr<Accessor::Impl> &impl);
- void delAccessor(uint32_t accessorId);
- };
-
- static std::unique_ptr<AccessorInvalidator> sInvalidator;
-
- static void invalidatorThread(
- std::map<uint32_t, const std::weak_ptr<Accessor::Impl>> &accessors,
- 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
-} // namespace V2_0
-} // namespace ufferpool
-} // namespace media
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_ACCESSORIMPL_H
diff --git a/media/bufferpool/aidl/default/Android.bp b/media/bufferpool/aidl/default/Android.bp
new file mode 100644
index 0000000..11a6163
--- /dev/null
+++ b/media/bufferpool/aidl/default/Android.bp
@@ -0,0 +1,50 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library {
+ name: "libstagefright_aidl_bufferpool2",
+ vendor_available: true,
+ min_sdk_version: "29",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media.swcodec",
+ "test_com.android.media.swcodec",
+ ],
+ srcs: [
+ "Accessor.cpp",
+ "BufferPool.cpp",
+ "BufferPoolClient.cpp",
+ "BufferStatus.cpp",
+ "ClientManager.cpp",
+ "Connection.cpp",
+ "Observer.cpp",
+ ],
+ export_include_dirs: [
+ "include",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "libcutils",
+ "libfmq",
+ "liblog",
+ "libutils",
+ "android.hardware.media.bufferpool2-V1-ndk",
+ ],
+ static_libs: [
+ "libaidlcommonsupport",
+ ],
+ export_shared_lib_headers: [
+ "libfmq",
+ "android.hardware.media.bufferpool2-V1-ndk",
+ ],
+ double_loadable: true,
+ cflags: [
+ "-DBUFFERPOOL_CLONE_HANDLES",
+ ],
+}
diff --git a/media/bufferpool/aidl/default/BufferPool.cpp b/media/bufferpool/aidl/default/BufferPool.cpp
new file mode 100644
index 0000000..ed4574f
--- /dev/null
+++ b/media/bufferpool/aidl/default/BufferPool.cpp
@@ -0,0 +1,540 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AidlBufferPool"
+//#define LOG_NDEBUG 0
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <time.h>
+#include <unistd.h>
+#include <utils/Log.h>
+#include <thread>
+#include "Accessor.h"
+#include "BufferPool.h"
+#include "Connection.h"
+#include "DataHelper.h"
+
+namespace aidl::android::hardware::media::bufferpool2::implementation {
+
+namespace {
+ static constexpr int64_t kCleanUpDurationMs = 500; // 0.5 sec
+ static constexpr int64_t kLogDurationMs = 5000; // 5 secs
+
+ static constexpr size_t kMinAllocBytesForEviction = 1024*1024*15;
+ static constexpr size_t kMinBufferCountForEviction = 25;
+ static constexpr size_t kMaxUnusedBufferCount = 64;
+ static constexpr size_t kUnusedBufferCountTarget = kMaxUnusedBufferCount - 16;
+}
+
+BufferPool::BufferPool()
+ : mTimestampMs(::android::elapsedRealtime()),
+ mLastCleanUpMs(mTimestampMs),
+ mLastLogMs(mTimestampMs),
+ mSeq(0),
+ mStartSeq(0) {
+ mValid = mInvalidationChannel.isValid();
+}
+
+
+// Statistics helper
+template<typename T, typename S>
+int percentage(T base, S total) {
+ return int(total ? 0.5 + 100. * static_cast<S>(base) / total : 0);
+}
+
+std::atomic<std::uint32_t> BufferPool::Invalidation::sInvSeqId(0);
+
+BufferPool::~BufferPool() {
+ std::lock_guard<std::mutex> lock(mMutex);
+ ALOGD("Destruction - bufferpool2 %p "
+ "cached: %zu/%zuM, %zu/%d%% in use; "
+ "allocs: %zu, %d%% recycled; "
+ "transfers: %zu, %d%% unfetched",
+ this, mStats.mBuffersCached, mStats.mSizeCached >> 20,
+ mStats.mBuffersInUse, percentage(mStats.mBuffersInUse, mStats.mBuffersCached),
+ mStats.mTotalAllocations, percentage(mStats.mTotalRecycles, mStats.mTotalAllocations),
+ mStats.mTotalTransfers,
+ percentage(mStats.mTotalTransfers - mStats.mTotalFetches, mStats.mTotalTransfers));
+}
+
+void BufferPool::Invalidation::onConnect(
+ ConnectionId conId, const std::shared_ptr<IObserver>& observer) {
+ mAcks[conId] = mInvalidationId; // starts from current invalidationId
+ mObservers.insert(std::make_pair(conId, observer));
+}
+
+void BufferPool::Invalidation::onClose(ConnectionId conId) {
+ mAcks.erase(conId);
+ mObservers.erase(conId);
+}
+
+void BufferPool::Invalidation::onAck(
+ ConnectionId conId,
+ uint32_t msgId) {
+ auto it = mAcks.find(conId);
+ if (it == mAcks.end()) {
+ ALOGW("ACK from inconsistent connection! %lld", (long long)conId);
+ return;
+ }
+ if (isMessageLater(msgId, it->second)) {
+ mAcks[conId] = msgId;
+ }
+}
+
+void BufferPool::Invalidation::onBufferInvalidated(
+ BufferId bufferId,
+ BufferInvalidationChannel &channel) {
+ for (auto it = mPendings.begin(); it != mPendings.end();) {
+ if (it->isInvalidated(bufferId)) {
+ uint32_t msgId = 0;
+ if (it->mNeedsAck) {
+ msgId = ++mInvalidationId;
+ if (msgId == 0) {
+ // wrap happens
+ msgId = ++mInvalidationId;
+ }
+ }
+ channel.postInvalidation(msgId, it->mFrom, it->mTo);
+ it = mPendings.erase(it);
+ continue;
+ }
+ ++it;
+ }
+}
+
+void BufferPool::Invalidation::onInvalidationRequest(
+ bool needsAck,
+ uint32_t from,
+ uint32_t to,
+ size_t left,
+ BufferInvalidationChannel &channel,
+ const std::shared_ptr<Accessor> &impl) {
+ uint32_t msgId = 0;
+ if (needsAck) {
+ msgId = ++mInvalidationId;
+ if (msgId == 0) {
+ // wrap happens
+ msgId = ++mInvalidationId;
+ }
+ }
+ ALOGV("bufferpool2 invalidation requested and queued");
+ if (left == 0) {
+ channel.postInvalidation(msgId, from, to);
+ } else {
+ ALOGV("bufferpoo2 invalidation requested and pending");
+ Pending pending(needsAck, from, to, left, impl);
+ mPendings.push_back(pending);
+ }
+ Accessor::sInvalidator->addAccessor(mId, impl);
+}
+
+void BufferPool::Invalidation::onHandleAck(
+ std::map<ConnectionId, const std::shared_ptr<IObserver>> *observers,
+ uint32_t *invalidationId) {
+ if (mInvalidationId != 0) {
+ *invalidationId = mInvalidationId;
+ std::set<int> deads;
+ for (auto it = mAcks.begin(); it != mAcks.end(); ++it) {
+ if (it->second != mInvalidationId) {
+ const std::shared_ptr<IObserver> observer = mObservers[it->first];
+ if (observer) {
+ observers->emplace(it->first, observer);
+ ALOGV("connection %lld will call observer (%u: %u)",
+ (long long)it->first, it->second, mInvalidationId);
+ // N.B: onMessage will be called later. ignore possibility of
+ // onMessage# oneway call being lost.
+ it->second = mInvalidationId;
+ } else {
+ ALOGV("bufferpool2 observer died %lld", (long long)it->first);
+ deads.insert(it->first);
+ }
+ }
+ }
+ if (deads.size() > 0) {
+ for (auto it = deads.begin(); it != deads.end(); ++it) {
+ onClose(*it);
+ }
+ }
+ }
+ if (mPendings.size() == 0) {
+ // All invalidation Ids are synced and no more pending invalidations.
+ Accessor::sInvalidator->delAccessor(mId);
+ }
+}
+
+bool BufferPool::handleOwnBuffer(
+ ConnectionId connectionId, BufferId bufferId) {
+
+ bool added = insert(&mUsingBuffers, connectionId, bufferId);
+ if (added) {
+ auto iter = mBuffers.find(bufferId);
+ iter->second->mOwnerCount++;
+ }
+ insert(&mUsingConnections, bufferId, connectionId);
+ return added;
+}
+
+bool BufferPool::handleReleaseBuffer(
+ ConnectionId connectionId, BufferId bufferId) {
+ bool deleted = erase(&mUsingBuffers, connectionId, bufferId);
+ if (deleted) {
+ auto iter = mBuffers.find(bufferId);
+ iter->second->mOwnerCount--;
+ if (iter->second->mOwnerCount == 0 &&
+ iter->second->mTransactionCount == 0) {
+ if (!iter->second->mInvalidated) {
+ mStats.onBufferUnused(iter->second->mAllocSize);
+ mFreeBuffers.insert(bufferId);
+ } else {
+ mStats.onBufferUnused(iter->second->mAllocSize);
+ mStats.onBufferEvicted(iter->second->mAllocSize);
+ mBuffers.erase(iter);
+ mInvalidation.onBufferInvalidated(bufferId, mInvalidationChannel);
+ }
+ }
+ }
+ erase(&mUsingConnections, bufferId, connectionId);
+ ALOGV("release buffer %u : %d", bufferId, deleted);
+ return deleted;
+}
+
+bool BufferPool::handleTransferTo(const BufferStatusMessage &message) {
+ auto completed = mCompletedTransactions.find(
+ message.transactionId);
+ if (completed != mCompletedTransactions.end()) {
+ // already completed
+ mCompletedTransactions.erase(completed);
+ return true;
+ }
+ // the buffer should exist and be owned.
+ auto bufferIter = mBuffers.find(message.bufferId);
+ if (bufferIter == mBuffers.end() ||
+ !contains(&mUsingBuffers, message.connectionId, FromAidl(message.bufferId))) {
+ return false;
+ }
+ auto found = mTransactions.find(message.transactionId);
+ if (found != mTransactions.end()) {
+ // transfer_from was received earlier.
+ found->second->mSender = message.connectionId;
+ found->second->mSenderValidated = true;
+ return true;
+ }
+ if (mConnectionIds.find(message.targetConnectionId) == mConnectionIds.end()) {
+ // N.B: it could be fake or receive connection already closed.
+ ALOGD("bufferpool2 %p receiver connection %lld is no longer valid",
+ this, (long long)message.targetConnectionId);
+ return false;
+ }
+ mStats.onBufferSent();
+ mTransactions.insert(std::make_pair(
+ message.transactionId,
+ std::make_unique<TransactionStatus>(message, mTimestampMs)));
+ insert(&mPendingTransactions, message.targetConnectionId,
+ FromAidl(message.transactionId));
+ bufferIter->second->mTransactionCount++;
+ return true;
+}
+
+bool BufferPool::handleTransferFrom(const BufferStatusMessage &message) {
+ auto found = mTransactions.find(message.transactionId);
+ if (found == mTransactions.end()) {
+ // TODO: is it feasible to check ownership here?
+ mStats.onBufferSent();
+ mTransactions.insert(std::make_pair(
+ message.transactionId,
+ std::make_unique<TransactionStatus>(message, mTimestampMs)));
+ insert(&mPendingTransactions, message.connectionId,
+ FromAidl(message.transactionId));
+ auto bufferIter = mBuffers.find(message.bufferId);
+ bufferIter->second->mTransactionCount++;
+ } else {
+ if (message.connectionId == found->second->mReceiver) {
+ found->second->mStatus = BufferStatus::TRANSFER_FROM;
+ }
+ }
+ return true;
+}
+
+bool BufferPool::handleTransferResult(const BufferStatusMessage &message) {
+ auto found = mTransactions.find(message.transactionId);
+ if (found != mTransactions.end()) {
+ bool deleted = erase(&mPendingTransactions, message.connectionId,
+ FromAidl(message.transactionId));
+ if (deleted) {
+ if (!found->second->mSenderValidated) {
+ mCompletedTransactions.insert(message.transactionId);
+ }
+ auto bufferIter = mBuffers.find(message.bufferId);
+ if (message.status == BufferStatus::TRANSFER_OK) {
+ handleOwnBuffer(message.connectionId, message.bufferId);
+ }
+ bufferIter->second->mTransactionCount--;
+ if (bufferIter->second->mOwnerCount == 0
+ && bufferIter->second->mTransactionCount == 0) {
+ if (!bufferIter->second->mInvalidated) {
+ mStats.onBufferUnused(bufferIter->second->mAllocSize);
+ mFreeBuffers.insert(message.bufferId);
+ } else {
+ mStats.onBufferUnused(bufferIter->second->mAllocSize);
+ mStats.onBufferEvicted(bufferIter->second->mAllocSize);
+ mBuffers.erase(bufferIter);
+ mInvalidation.onBufferInvalidated(message.bufferId, mInvalidationChannel);
+ }
+ }
+ mTransactions.erase(found);
+ }
+ ALOGV("transfer finished %llu %u - %d", (unsigned long long)message.transactionId,
+ message.bufferId, deleted);
+ return deleted;
+ }
+ ALOGV("transfer not found %llu %u", (unsigned long long)message.transactionId,
+ message.bufferId);
+ return false;
+}
+
+void BufferPool::processStatusMessages() {
+ std::vector<BufferStatusMessage> messages;
+ mObserver.getBufferStatusChanges(messages);
+ mTimestampMs = ::android::elapsedRealtime();
+ for (BufferStatusMessage& message: messages) {
+ bool ret = false;
+ switch (message.status) {
+ case BufferStatus::NOT_USED:
+ ret = handleReleaseBuffer(
+ message.connectionId, message.bufferId);
+ break;
+ case BufferStatus::USED:
+ // not happening
+ break;
+ case BufferStatus::TRANSFER_TO:
+ ret = handleTransferTo(message);
+ break;
+ case BufferStatus::TRANSFER_FROM:
+ ret = handleTransferFrom(message);
+ break;
+ case BufferStatus::TRANSFER_TIMEOUT:
+ // TODO
+ break;
+ case BufferStatus::TRANSFER_LOST:
+ // TODO
+ break;
+ case BufferStatus::TRANSFER_FETCH:
+ // not happening
+ break;
+ case BufferStatus::TRANSFER_OK:
+ case BufferStatus::TRANSFER_ERROR:
+ ret = handleTransferResult(message);
+ break;
+ case BufferStatus::INVALIDATION_ACK:
+ mInvalidation.onAck(message.connectionId, message.bufferId);
+ ret = true;
+ break;
+ }
+ if (ret == false) {
+ ALOGW("buffer status message processing failure - message : %d connection : %lld",
+ message.status, (long long)message.connectionId);
+ }
+ }
+ messages.clear();
+}
+
+bool BufferPool::handleClose(ConnectionId connectionId) {
+ // Cleaning buffers
+ auto buffers = mUsingBuffers.find(connectionId);
+ if (buffers != mUsingBuffers.end()) {
+ for (const BufferId& bufferId : buffers->second) {
+ bool deleted = erase(&mUsingConnections, bufferId, connectionId);
+ if (deleted) {
+ auto bufferIter = mBuffers.find(bufferId);
+ bufferIter->second->mOwnerCount--;
+ if (bufferIter->second->mOwnerCount == 0 &&
+ bufferIter->second->mTransactionCount == 0) {
+ // TODO: handle freebuffer insert fail
+ if (!bufferIter->second->mInvalidated) {
+ mStats.onBufferUnused(bufferIter->second->mAllocSize);
+ mFreeBuffers.insert(bufferId);
+ } else {
+ mStats.onBufferUnused(bufferIter->second->mAllocSize);
+ mStats.onBufferEvicted(bufferIter->second->mAllocSize);
+ mBuffers.erase(bufferIter);
+ mInvalidation.onBufferInvalidated(bufferId, mInvalidationChannel);
+ }
+ }
+ }
+ }
+ mUsingBuffers.erase(buffers);
+ }
+
+ // Cleaning transactions
+ auto pending = mPendingTransactions.find(connectionId);
+ if (pending != mPendingTransactions.end()) {
+ for (const TransactionId& transactionId : pending->second) {
+ auto iter = mTransactions.find(transactionId);
+ if (iter != mTransactions.end()) {
+ if (!iter->second->mSenderValidated) {
+ mCompletedTransactions.insert(transactionId);
+ }
+ BufferId bufferId = iter->second->mBufferId;
+ auto bufferIter = mBuffers.find(bufferId);
+ bufferIter->second->mTransactionCount--;
+ if (bufferIter->second->mOwnerCount == 0 &&
+ bufferIter->second->mTransactionCount == 0) {
+ // TODO: handle freebuffer insert fail
+ if (!bufferIter->second->mInvalidated) {
+ mStats.onBufferUnused(bufferIter->second->mAllocSize);
+ mFreeBuffers.insert(bufferId);
+ } else {
+ mStats.onBufferUnused(bufferIter->second->mAllocSize);
+ mStats.onBufferEvicted(bufferIter->second->mAllocSize);
+ mBuffers.erase(bufferIter);
+ mInvalidation.onBufferInvalidated(bufferId, mInvalidationChannel);
+ }
+ }
+ mTransactions.erase(iter);
+ }
+ }
+ }
+ mConnectionIds.erase(connectionId);
+ return true;
+}
+
+bool BufferPool::getFreeBuffer(
+ const std::shared_ptr<BufferPoolAllocator> &allocator,
+ const std::vector<uint8_t> ¶ms, BufferId *pId,
+ const native_handle_t** handle) {
+ auto bufferIt = mFreeBuffers.begin();
+ for (;bufferIt != mFreeBuffers.end(); ++bufferIt) {
+ BufferId bufferId = *bufferIt;
+ if (allocator->compatible(params, mBuffers[bufferId]->mConfig)) {
+ break;
+ }
+ }
+ if (bufferIt != mFreeBuffers.end()) {
+ BufferId id = *bufferIt;
+ mFreeBuffers.erase(bufferIt);
+ mStats.onBufferRecycled(mBuffers[id]->mAllocSize);
+ *handle = mBuffers[id]->handle();
+ *pId = id;
+ ALOGV("recycle a buffer %u %p", id, *handle);
+ return true;
+ }
+ return false;
+}
+
+BufferPoolStatus BufferPool::addNewBuffer(
+ const std::shared_ptr<BufferPoolAllocation> &alloc,
+ const size_t allocSize,
+ const std::vector<uint8_t> ¶ms,
+ BufferId *pId,
+ const native_handle_t** handle) {
+
+ BufferId bufferId = mSeq++;
+ if (mSeq == Connection::SYNC_BUFFERID) {
+ mSeq = 0;
+ }
+ std::unique_ptr<InternalBuffer> buffer =
+ std::make_unique<InternalBuffer>(
+ bufferId, alloc, allocSize, params);
+ if (buffer) {
+ auto res = mBuffers.insert(std::make_pair(
+ bufferId, std::move(buffer)));
+ if (res.second) {
+ mStats.onBufferAllocated(allocSize);
+ *handle = alloc->handle();
+ *pId = bufferId;
+ return ResultStatus::OK;
+ }
+ }
+ return ResultStatus::NO_MEMORY;
+}
+
+void BufferPool::cleanUp(bool clearCache) {
+ if (clearCache || mTimestampMs > mLastCleanUpMs + kCleanUpDurationMs ||
+ mStats.buffersNotInUse() > kMaxUnusedBufferCount) {
+ mLastCleanUpMs = mTimestampMs;
+ if (mTimestampMs > mLastLogMs + kLogDurationMs ||
+ mStats.buffersNotInUse() > kMaxUnusedBufferCount) {
+ mLastLogMs = mTimestampMs;
+ ALOGD("bufferpool2 %p : %zu(%zu size) total buffers - "
+ "%zu(%zu size) used buffers - %zu/%zu (recycle/alloc) - "
+ "%zu/%zu (fetch/transfer)",
+ this, mStats.mBuffersCached, mStats.mSizeCached,
+ mStats.mBuffersInUse, mStats.mSizeInUse,
+ mStats.mTotalRecycles, mStats.mTotalAllocations,
+ mStats.mTotalFetches, mStats.mTotalTransfers);
+ }
+ for (auto freeIt = mFreeBuffers.begin(); freeIt != mFreeBuffers.end();) {
+ if (!clearCache && mStats.buffersNotInUse() <= kUnusedBufferCountTarget &&
+ (mStats.mSizeCached < kMinAllocBytesForEviction ||
+ mBuffers.size() < kMinBufferCountForEviction)) {
+ break;
+ }
+ auto it = mBuffers.find(*freeIt);
+ if (it != mBuffers.end() &&
+ it->second->mOwnerCount == 0 && it->second->mTransactionCount == 0) {
+ mStats.onBufferEvicted(it->second->mAllocSize);
+ mBuffers.erase(it);
+ freeIt = mFreeBuffers.erase(freeIt);
+ } else {
+ ++freeIt;
+ ALOGW("bufferpool2 inconsistent!");
+ }
+ }
+ }
+}
+
+void BufferPool::invalidate(
+ bool needsAck, BufferId from, BufferId to,
+ const std::shared_ptr<Accessor> &impl) {
+ for (auto freeIt = mFreeBuffers.begin(); freeIt != mFreeBuffers.end();) {
+ if (isBufferInRange(from, to, *freeIt)) {
+ auto it = mBuffers.find(*freeIt);
+ if (it != mBuffers.end() &&
+ it->second->mOwnerCount == 0 && it->second->mTransactionCount == 0) {
+ mStats.onBufferEvicted(it->second->mAllocSize);
+ mBuffers.erase(it);
+ freeIt = mFreeBuffers.erase(freeIt);
+ continue;
+ } else {
+ ALOGW("bufferpool2 inconsistent!");
+ }
+ }
+ ++freeIt;
+ }
+
+ size_t left = 0;
+ for (auto it = mBuffers.begin(); it != mBuffers.end(); ++it) {
+ if (isBufferInRange(from, to, it->first)) {
+ it->second->invalidate();
+ ++left;
+ }
+ }
+ mInvalidation.onInvalidationRequest(needsAck, from, to, left, mInvalidationChannel, impl);
+}
+
+void BufferPool::flush(const std::shared_ptr<Accessor> &impl) {
+ BufferId from = mStartSeq;
+ BufferId to = mSeq;
+ mStartSeq = mSeq;
+ // TODO: needsAck params
+ ALOGV("buffer invalidation request bp:%u %u %u", mInvalidation.mId, from, to);
+ if (from != to) {
+ invalidate(true, from, to, impl);
+ }
+}
+
+} // namespace aidl::android::hardware::media::bufferpool2::implementation
diff --git a/media/bufferpool/aidl/default/BufferPool.h b/media/bufferpool/aidl/default/BufferPool.h
new file mode 100644
index 0000000..1529a53
--- /dev/null
+++ b/media/bufferpool/aidl/default/BufferPool.h
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <map>
+#include <set>
+#include <vector>
+#include <mutex>
+#include <condition_variable>
+#include <utils/Timers.h>
+
+#include "BufferStatus.h"
+
+namespace aidl::android::hardware::media::bufferpool2::implementation {
+
+using BufferStatus = aidl::android::hardware::media::bufferpool2::BufferStatus;
+using BufferStatusMessage = aidl::android::hardware::media::bufferpool2::BufferStatusMessage;
+
+struct Accessor;
+struct InternalBuffer;
+struct TransactionStatus;
+
+/**
+ * Buffer pool implementation.
+ *
+ * Handles buffer status messages. Handles buffer allocation/recycling.
+ * Handles buffer transfer between buffer pool clients.
+ */
+struct BufferPool {
+private:
+ std::mutex mMutex;
+ int64_t mTimestampMs;
+ int64_t mLastCleanUpMs;
+ int64_t mLastLogMs;
+ BufferId mSeq;
+ BufferId mStartSeq;
+ bool mValid;
+ BufferStatusObserver mObserver;
+ BufferInvalidationChannel mInvalidationChannel;
+
+ std::map<ConnectionId, std::set<BufferId>> mUsingBuffers;
+ std::map<BufferId, std::set<ConnectionId>> mUsingConnections;
+
+ std::map<ConnectionId, std::set<TransactionId>> mPendingTransactions;
+ // Transactions completed before TRANSFER_TO message arrival.
+ // Fetch does not occur for the transactions.
+ // Only transaction id is kept for the transactions in short duration.
+ std::set<TransactionId> mCompletedTransactions;
+ // Currently active(pending) transations' status & information.
+ std::map<TransactionId, std::unique_ptr<TransactionStatus>>
+ mTransactions;
+
+ std::map<BufferId, std::unique_ptr<InternalBuffer>> mBuffers;
+ std::set<BufferId> mFreeBuffers;
+ std::set<ConnectionId> mConnectionIds;
+
+ struct Invalidation {
+ static std::atomic<std::uint32_t> sInvSeqId;
+
+ struct Pending {
+ bool mNeedsAck;
+ uint32_t mFrom;
+ uint32_t mTo;
+ size_t mLeft;
+ const std::weak_ptr<Accessor> mImpl;
+ Pending(bool needsAck, uint32_t from, uint32_t to, size_t left,
+ const std::shared_ptr<Accessor> &impl)
+ : mNeedsAck(needsAck),
+ mFrom(from),
+ mTo(to),
+ mLeft(left),
+ mImpl(impl)
+ {}
+
+ bool isInvalidated(uint32_t bufferId) {
+ return isBufferInRange(mFrom, mTo, bufferId) && --mLeft == 0;
+ }
+ };
+
+ std::list<Pending> mPendings;
+ std::map<ConnectionId, uint32_t> mAcks;
+ std::map<ConnectionId, const std::shared_ptr<IObserver>> mObservers;
+ uint32_t mInvalidationId;
+ uint32_t mId;
+
+ Invalidation() : mInvalidationId(0), mId(sInvSeqId.fetch_add(1)) {}
+
+ void onConnect(ConnectionId conId, const std::shared_ptr<IObserver> &observer);
+
+ void onClose(ConnectionId conId);
+
+ void onAck(ConnectionId conId, uint32_t msgId);
+
+ void onBufferInvalidated(
+ BufferId bufferId,
+ BufferInvalidationChannel &channel);
+
+ void onInvalidationRequest(
+ bool needsAck, uint32_t from, uint32_t to, size_t left,
+ BufferInvalidationChannel &channel,
+ const std::shared_ptr<Accessor> &impl);
+
+ void onHandleAck(
+ std::map<ConnectionId, const std::shared_ptr<IObserver>> *observers,
+ uint32_t *invalidationId);
+ } mInvalidation;
+ /// Buffer pool statistics which tracks allocation and transfer statistics.
+ struct Stats {
+ /// Total size of allocations which are used or available to use.
+ /// (bytes or pixels)
+ size_t mSizeCached;
+ /// # of cached buffers which are used or available to use.
+ size_t mBuffersCached;
+ /// Total size of allocations which are currently used. (bytes or pixels)
+ size_t mSizeInUse;
+ /// # of currently used buffers
+ size_t mBuffersInUse;
+
+ /// # of allocations called on bufferpool. (# of fetched from BlockPool)
+ size_t mTotalAllocations;
+ /// # of allocations that were served from the cache.
+ /// (# of allocator alloc prevented)
+ size_t mTotalRecycles;
+ /// # of buffer transfers initiated.
+ size_t mTotalTransfers;
+ /// # of transfers that had to be fetched.
+ size_t mTotalFetches;
+
+ Stats()
+ : mSizeCached(0), mBuffersCached(0), mSizeInUse(0), mBuffersInUse(0),
+ mTotalAllocations(0), mTotalRecycles(0), mTotalTransfers(0), mTotalFetches(0) {}
+
+ /// # of currently unused buffers
+ size_t buffersNotInUse() const {
+ ALOG_ASSERT(mBuffersCached >= mBuffersInUse);
+ return mBuffersCached - mBuffersInUse;
+ }
+
+ /// A new buffer is allocated on an allocation request.
+ void onBufferAllocated(size_t allocSize) {
+ mSizeCached += allocSize;
+ mBuffersCached++;
+
+ mSizeInUse += allocSize;
+ mBuffersInUse++;
+
+ mTotalAllocations++;
+ }
+
+ /// A buffer is evicted and destroyed.
+ void onBufferEvicted(size_t allocSize) {
+ mSizeCached -= allocSize;
+ mBuffersCached--;
+ }
+
+ /// A buffer is recycled on an allocation request.
+ void onBufferRecycled(size_t allocSize) {
+ mSizeInUse += allocSize;
+ mBuffersInUse++;
+
+ mTotalAllocations++;
+ mTotalRecycles++;
+ }
+
+ /// A buffer is available to be recycled.
+ void onBufferUnused(size_t allocSize) {
+ mSizeInUse -= allocSize;
+ mBuffersInUse--;
+ }
+
+ /// A buffer transfer is initiated.
+ void onBufferSent() {
+ mTotalTransfers++;
+ }
+
+ /// A buffer fetch is invoked by a buffer transfer.
+ void onBufferFetched() {
+ mTotalFetches++;
+ }
+ } mStats;
+
+ bool isValid() {
+ return mValid;
+ }
+
+ void invalidate(bool needsAck, BufferId from, BufferId to,
+ const std::shared_ptr<Accessor> &impl);
+
+ static void createInvalidator();
+
+public:
+ /** Creates a buffer pool. */
+ BufferPool();
+
+ /** Destroys a buffer pool. */
+ ~BufferPool();
+
+ /**
+ * Processes all pending buffer status messages, and returns the result.
+ * Each status message is handled by methods with 'handle' prefix.
+ */
+ void processStatusMessages();
+
+ /**
+ * Handles a buffer being owned by a connection.
+ *
+ * @param connectionId the id of the buffer owning connection.
+ * @param bufferId the id of the buffer.
+ *
+ * @return {@code true} when the buffer is owned,
+ * {@code false} otherwise.
+ */
+ bool handleOwnBuffer(ConnectionId connectionId, BufferId bufferId);
+
+ /**
+ * Handles a buffer being released by a connection.
+ *
+ * @param connectionId the id of the buffer owning connection.
+ * @param bufferId the id of the buffer.
+ *
+ * @return {@code true} when the buffer ownership is released,
+ * {@code false} otherwise.
+ */
+ bool handleReleaseBuffer(ConnectionId connectionId, BufferId bufferId);
+
+ /**
+ * Handles a transfer transaction start message from the sender.
+ *
+ * @param message a buffer status message for the transaction.
+ *
+ * @result {@code true} when transfer_to message is acknowledged,
+ * {@code false} otherwise.
+ */
+ bool handleTransferTo(const BufferStatusMessage &message);
+
+ /**
+ * Handles a transfer transaction being acked by the receiver.
+ *
+ * @param message a buffer status message for the transaction.
+ *
+ * @result {@code true} when transfer_from message is acknowledged,
+ * {@code false} otherwise.
+ */
+ bool handleTransferFrom(const BufferStatusMessage &message);
+
+ /**
+ * Handles a transfer transaction result message from the receiver.
+ *
+ * @param message a buffer status message for the transaction.
+ *
+ * @result {@code true} when the existing transaction is finished,
+ * {@code false} otherwise.
+ */
+ bool handleTransferResult(const BufferStatusMessage &message);
+
+ /**
+ * Handles a connection being closed, and returns the result. All the
+ * buffers and transactions owned by the connection will be cleaned up.
+ * The related FMQ will be cleaned up too.
+ *
+ * @param connectionId the id of the connection.
+ *
+ * @result {@code true} when the connection existed,
+ * {@code false} otherwise.
+ */
+ bool handleClose(ConnectionId connectionId);
+
+ /**
+ * Recycles a existing free buffer if it is possible.
+ *
+ * @param allocator the buffer allocator
+ * @param params the allocation parameters.
+ * @param pId the id of the recycled buffer.
+ * @param handle the native handle of the recycled buffer.
+ *
+ * @return {@code true} when a buffer is recycled, {@code false}
+ * otherwise.
+ */
+ bool getFreeBuffer(
+ const std::shared_ptr<BufferPoolAllocator> &allocator,
+ const std::vector<uint8_t> ¶ms,
+ BufferId *pId, const native_handle_t **handle);
+
+ /**
+ * Adds a newly allocated buffer to bufferpool.
+ *
+ * @param alloc the newly allocated buffer.
+ * @param allocSize the size of the newly allocated buffer.
+ * @param params the allocation parameters.
+ * @param pId the buffer id for the newly allocated buffer.
+ * @param handle the native handle for the newly allocated buffer.
+ *
+ * @return OK when an allocation is successfully allocated.
+ * NO_MEMORY when there is no memory.
+ * CRITICAL_ERROR otherwise.
+ */
+ BufferPoolStatus addNewBuffer(
+ const std::shared_ptr<BufferPoolAllocation> &alloc,
+ const size_t allocSize,
+ const std::vector<uint8_t> ¶ms,
+ BufferId *pId,
+ const native_handle_t **handle);
+
+ /**
+ * Processes pending buffer status messages and performs periodic cache
+ * cleaning.
+ *
+ * @param clearCache if clearCache is true, it frees all buffers
+ * waiting to be recycled.
+ */
+ void cleanUp(bool clearCache = false);
+
+ /**
+ * Processes pending buffer status messages and invalidate all current
+ * free buffers. Active buffers are invalidated after being inactive.
+ */
+ void flush(const std::shared_ptr<Accessor> &impl);
+
+ friend struct Accessor;
+};
+
+
+} // namespace aidl::android::hardware::media::bufferpool2::implementation
diff --git a/media/bufferpool/aidl/default/BufferPoolClient.cpp b/media/bufferpool/aidl/default/BufferPoolClient.cpp
index cda23ff..e9777d8 100644
--- a/media/bufferpool/aidl/default/BufferPoolClient.cpp
+++ b/media/bufferpool/aidl/default/BufferPoolClient.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,33 +14,37 @@
* limitations under the License.
*/
-#define LOG_TAG "BufferPoolClient"
+#define LOG_TAG "AidlBufferPoolCli"
//#define LOG_NDEBUG 0
#include <thread>
+#include <aidlcommonsupport/NativeHandle.h>
#include <utils/Log.h>
#include "BufferPoolClient.h"
+#include "Accessor.h"
#include "Connection.h"
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
-namespace V2_0 {
-namespace implementation {
+namespace aidl::android::hardware::media::bufferpool2::implementation {
-static constexpr int64_t kReceiveTimeoutUs = 2000000; // 2s
+using aidl::android::hardware::media::bufferpool2::IConnection;
+using aidl::android::hardware::media::bufferpool2::ResultStatus;
+using FetchInfo = aidl::android::hardware::media::bufferpool2::IConnection::FetchInfo;
+using FetchResult = aidl::android::hardware::media::bufferpool2::IConnection::FetchResult;
+
+static constexpr int64_t kReceiveTimeoutMs = 2000; // 2s
static constexpr int kPostMaxRetry = 3;
-static constexpr int kCacheTtlUs = 1000000; // TODO: tune
+static constexpr int kCacheTtlMs = 1000;
static constexpr size_t kMaxCachedBufferCount = 64;
static constexpr size_t kCachedBufferCountTarget = kMaxCachedBufferCount - 16;
class BufferPoolClient::Impl
: public std::enable_shared_from_this<BufferPoolClient::Impl> {
public:
- explicit Impl(const sp<Accessor> &accessor, const sp<IObserver> &observer);
+ explicit Impl(const std::shared_ptr<Accessor> &accessor,
+ const std::shared_ptr<IObserver> &observer);
- explicit Impl(const sp<IAccessor> &accessor, const sp<IObserver> &observer);
+ explicit Impl(const std::shared_ptr<IAccessor> &accessor,
+ const std::shared_ptr<IObserver> &observer);
bool isValid() {
return mValid;
@@ -54,35 +58,35 @@
return mConnectionId;
}
- sp<IAccessor> &getAccessor() {
+ std::shared_ptr<IAccessor> &getAccessor() {
return mAccessor;
}
- bool isActive(int64_t *lastTransactionUs, bool clearCache);
+ bool isActive(int64_t *lastTransactionMs, bool clearCache);
void receiveInvalidation(uint32_t msgID);
- ResultStatus flush();
+ BufferPoolStatus flush();
- ResultStatus allocate(const std::vector<uint8_t> ¶ms,
+ BufferPoolStatus allocate(const std::vector<uint8_t> ¶ms,
native_handle_t **handle,
std::shared_ptr<BufferPoolData> *buffer);
- ResultStatus receive(
+ BufferPoolStatus receive(
TransactionId transactionId, BufferId bufferId,
- int64_t timestampUs,
+ int64_t timestampMs,
native_handle_t **handle, std::shared_ptr<BufferPoolData> *buffer);
void postBufferRelease(BufferId bufferId);
bool postSend(
BufferId bufferId, ConnectionId receiver,
- TransactionId *transactionId, int64_t *timestampUs);
+ TransactionId *transactionId, int64_t *timestampMs);
private:
bool postReceive(
BufferId bufferId, TransactionId transactionId,
- int64_t timestampUs);
+ int64_t timestampMs);
bool postReceiveResult(
BufferId bufferId, TransactionId transactionId, bool result, bool *needsSync);
@@ -97,11 +101,11 @@
void invalidateRange(BufferId from, BufferId to);
- ResultStatus allocateBufferHandle(
+ BufferPoolStatus allocateBufferHandle(
const std::vector<uint8_t>& params, BufferId *bufferId,
native_handle_t **handle);
- ResultStatus fetchBufferHandle(
+ BufferPoolStatus fetchBufferHandle(
TransactionId transactionId, BufferId bufferId,
native_handle_t **handle);
@@ -110,12 +114,12 @@
bool mLocal;
bool mValid;
- sp<IAccessor> mAccessor;
- sp<Connection> mLocalConnection;
- sp<IConnection> mRemoteConnection;
+ std::shared_ptr<IAccessor> mAccessor;
+ std::shared_ptr<Connection> mLocalConnection;
+ std::shared_ptr<IConnection> mRemoteConnection;
uint32_t mSeqId;
ConnectionId mConnectionId;
- int64_t mLastEvictCacheUs;
+ int64_t mLastEvictCacheMs;
std::unique_ptr<BufferInvalidationListener> mInvalidationListener;
// CachedBuffers
@@ -125,18 +129,19 @@
std::condition_variable mCreateCv;
std::map<BufferId, std::unique_ptr<ClientBuffer>> mBuffers;
int mActive;
- int64_t mLastChangeUs;
+ int64_t mLastChangeMs;
- BufferCache() : mCreating(false), mActive(0), mLastChangeUs(getTimestampNow()) {}
+ BufferCache() : mCreating(false), mActive(0),
+ mLastChangeMs(::android::elapsedRealtime()) {}
void incActive_l() {
++mActive;
- mLastChangeUs = getTimestampNow();
+ mLastChangeMs = ::android::elapsedRealtime();
}
void decActive_l() {
--mActive;
- mLastChangeUs = getTimestampNow();
+ mLastChangeMs = ::android::elapsedRealtime();
}
int cachedBufferCount() const {
@@ -147,7 +152,6 @@
// FMQ - release notifier
struct ReleaseCache {
std::mutex mLock;
- // TODO: use only one list?(using one list may dealy sending messages?)
std::list<BufferId> mReleasingIds;
std::list<BufferId> mReleasedIds;
uint32_t mInvalidateId; // TODO: invalidation ACK to bufferpool
@@ -158,7 +162,7 @@
} mReleasing;
// This lock is held during synchronization from remote side.
- // In order to minimize remote calls and locking durtaion, this lock is held
+ // In order to minimize remote calls and locking duration, this lock is held
// by best effort approach using try_lock().
std::mutex mRemoteSyncLock;
};
@@ -181,7 +185,7 @@
struct BufferPoolClient::Impl::ClientBuffer {
private:
- int64_t mExpireUs;
+ int64_t mExpireMs;
bool mHasCache;
ConnectionId mConnectionId;
BufferId mId;
@@ -189,7 +193,7 @@
std::weak_ptr<BufferPoolData> mCache;
void updateExpire() {
- mExpireUs = getTimestampNow() + kCacheTtlUs;
+ mExpireMs = ::android::elapsedRealtime() + kCacheTtlMs;
}
public:
@@ -197,7 +201,7 @@
ConnectionId connectionId, BufferId id, native_handle_t *handle)
: mHasCache(false), mConnectionId(connectionId),
mId(id), mHandle(handle) {
- mExpireUs = getTimestampNow() + kCacheTtlUs;
+ mExpireMs = ::android::elapsedRealtime() + kCacheTtlMs;
}
~ClientBuffer() {
@@ -212,8 +216,8 @@
}
bool expire() const {
- int64_t now = getTimestampNow();
- return now >= mExpireUs;
+ int64_t now = ::android::elapsedRealtime();
+ return now >= mExpireMs;
}
bool hasCache() const {
@@ -265,20 +269,21 @@
}
};
-BufferPoolClient::Impl::Impl(const sp<Accessor> &accessor, const sp<IObserver> &observer)
+BufferPoolClient::Impl::Impl(const std::shared_ptr<Accessor> &accessor,
+ const std::shared_ptr<IObserver> &observer)
: mLocal(true), mValid(false), mAccessor(accessor), mSeqId(0),
- mLastEvictCacheUs(getTimestampNow()) {
- const StatusDescriptor *statusDesc;
- const InvalidationDescriptor *invDesc;
- ResultStatus status = accessor->connect(
+ mLastEvictCacheMs(::android::elapsedRealtime()) {
+ StatusDescriptor statusDesc;
+ InvalidationDescriptor invDesc;
+ BufferPoolStatus status = accessor->connect(
observer, true,
&mLocalConnection, &mConnectionId, &mReleasing.mInvalidateId,
&statusDesc, &invDesc);
if (status == ResultStatus::OK) {
mReleasing.mStatusChannel =
- std::make_unique<BufferStatusChannel>(*statusDesc);
+ std::make_unique<BufferStatusChannel>(statusDesc);
mInvalidationListener =
- std::make_unique<BufferInvalidationListener>(*invDesc);
+ std::make_unique<BufferInvalidationListener>(invDesc);
mValid = mReleasing.mStatusChannel &&
mReleasing.mStatusChannel->isValid() &&
mInvalidationListener &&
@@ -286,46 +291,36 @@
}
}
-BufferPoolClient::Impl::Impl(const sp<IAccessor> &accessor, const sp<IObserver> &observer)
+BufferPoolClient::Impl::Impl(const std::shared_ptr<IAccessor> &accessor,
+ const std::shared_ptr<IObserver> &observer)
: mLocal(false), mValid(false), mAccessor(accessor), mSeqId(0),
- mLastEvictCacheUs(getTimestampNow()) {
+ mLastEvictCacheMs(::android::elapsedRealtime()) {
+ IAccessor::ConnectionInfo conInfo;
bool valid = false;
- sp<IConnection>& outConnection = mRemoteConnection;
- ConnectionId& id = mConnectionId;
- uint32_t& outMsgId = mReleasing.mInvalidateId;
- std::unique_ptr<BufferStatusChannel>& outChannel =
- mReleasing.mStatusChannel;
- std::unique_ptr<BufferInvalidationListener>& outObserver =
- mInvalidationListener;
- Return<void> transResult = accessor->connect(
- observer,
- [&valid, &outConnection, &id, &outMsgId, &outChannel, &outObserver]
- (ResultStatus status, sp<IConnection> connection,
- ConnectionId connectionId, uint32_t msgId,
- const StatusDescriptor& statusDesc,
- const InvalidationDescriptor& invDesc) {
- if (status == ResultStatus::OK) {
- outConnection = connection;
- id = connectionId;
- outMsgId = msgId;
- outChannel = std::make_unique<BufferStatusChannel>(statusDesc);
- outObserver = std::make_unique<BufferInvalidationListener>(invDesc);
- if (outChannel && outChannel->isValid() &&
- outObserver && outObserver->isValid()) {
- valid = true;
- }
- }
- });
- mValid = transResult.isOk() && valid;
+ if(accessor->connect(observer, &conInfo).isOk()) {
+ auto channel = std::make_unique<BufferStatusChannel>(conInfo.toFmqDesc);
+ auto observer = std::make_unique<BufferInvalidationListener>(conInfo.fromFmqDesc);
+
+ if (channel && channel->isValid()
+ && observer && observer->isValid()) {
+ mRemoteConnection = conInfo.connection;
+ mConnectionId = conInfo.connectionId;
+ mReleasing.mInvalidateId = conInfo.msgId;
+ mReleasing.mStatusChannel = std::move(channel);
+ mInvalidationListener = std::move(observer);
+ valid = true;
+ }
+ }
+ mValid = valid;
}
-bool BufferPoolClient::Impl::isActive(int64_t *lastTransactionUs, bool clearCache) {
+bool BufferPoolClient::Impl::isActive(int64_t *lastTransactionMs, bool clearCache) {
bool active = false;
{
std::lock_guard<std::mutex> lock(mCache.mLock);
syncReleased();
evictCaches(clearCache);
- *lastTransactionUs = mCache.mLastChangeUs;
+ *lastTransactionMs = mCache.mLastChangeMs;
active = mCache.mActive > 0;
}
if (mValid && mLocal && mLocalConnection) {
@@ -341,7 +336,7 @@
// TODO: evict cache required?
}
-ResultStatus BufferPoolClient::Impl::flush() {
+BufferPoolStatus BufferPoolClient::Impl::flush() {
if (!mLocal || !mLocalConnection || !mValid) {
return ResultStatus::CRITICAL_ERROR;
}
@@ -353,7 +348,7 @@
}
}
-ResultStatus BufferPoolClient::Impl::allocate(
+BufferPoolStatus BufferPoolClient::Impl::allocate(
const std::vector<uint8_t> ¶ms,
native_handle_t **pHandle,
std::shared_ptr<BufferPoolData> *buffer) {
@@ -363,7 +358,7 @@
BufferId bufferId;
native_handle_t *handle = nullptr;
buffer->reset();
- ResultStatus status = allocateBufferHandle(params, &bufferId, &handle);
+ BufferPoolStatus status = allocateBufferHandle(params, &bufferId, &handle);
if (status == ResultStatus::OK) {
if (handle) {
std::unique_lock<std::mutex> lock(mCache.mLock);
@@ -398,20 +393,20 @@
return status;
}
-ResultStatus BufferPoolClient::Impl::receive(
- TransactionId transactionId, BufferId bufferId, int64_t timestampUs,
+BufferPoolStatus BufferPoolClient::Impl::receive(
+ TransactionId transactionId, BufferId bufferId, int64_t timestampMs,
native_handle_t **pHandle,
std::shared_ptr<BufferPoolData> *buffer) {
if (!mValid) {
return ResultStatus::CRITICAL_ERROR;
}
- if (timestampUs != 0) {
- timestampUs += kReceiveTimeoutUs;
+ if (timestampMs != 0) {
+ timestampMs += kReceiveTimeoutMs;
}
- if (!postReceive(bufferId, transactionId, timestampUs)) {
+ if (!postReceive(bufferId, transactionId, timestampMs)) {
return ResultStatus::CRITICAL_ERROR;
}
- ResultStatus status = ResultStatus::CRITICAL_ERROR;
+ BufferPoolStatus status = ResultStatus::CRITICAL_ERROR;
buffer->reset();
while(1) {
std::unique_lock<std::mutex> lock(mCache.mLock);
@@ -505,7 +500,7 @@
// TODO: revise ad-hoc posting data structure
bool BufferPoolClient::Impl::postSend(
BufferId bufferId, ConnectionId receiver,
- TransactionId *transactionId, int64_t *timestampUs) {
+ TransactionId *transactionId, int64_t *timestampMs) {
{
// TODO: don't need to call syncReleased every time
std::lock_guard<std::mutex> lock(mCache.mLock);
@@ -515,7 +510,7 @@
bool needsSync = false;
{
std::lock_guard<std::mutex> lock(mReleasing.mLock);
- *timestampUs = getTimestampNow();
+ *timestampMs = ::android::elapsedRealtime();
*transactionId = (mConnectionId << 32) | mSeqId++;
// TODO: retry, add timeout, target?
ret = mReleasing.mStatusChannel->postBufferStatusMessage(
@@ -533,11 +528,11 @@
}
bool BufferPoolClient::Impl::postReceive(
- BufferId bufferId, TransactionId transactionId, int64_t timestampUs) {
+ BufferId bufferId, TransactionId transactionId, int64_t timestampMs) {
for (int i = 0; i < kPostMaxRetry; ++i) {
std::unique_lock<std::mutex> lock(mReleasing.mLock);
- int64_t now = getTimestampNow();
- if (timestampUs == 0 || now < timestampUs) {
+ int64_t now = ::android::elapsedRealtime();
+ if (timestampMs == 0 || now < timestampMs) {
bool result = mReleasing.mStatusChannel->postBufferStatusMessage(
transactionId, bufferId, BufferStatus::TRANSFER_FROM,
mConnectionId, -1, mReleasing.mReleasingIds,
@@ -579,16 +574,7 @@
needsSync = mReleasing.mStatusChannel->needsSync();
}
if (needsSync) {
- TransactionId transactionId = (mConnectionId << 32);
- BufferId bufferId = Connection::SYNC_BUFFERID;
- Return<void> transResult = mRemoteConnection->fetch(
- transactionId, bufferId,
- []
- (ResultStatus outStatus, Buffer outBuffer) {
- (void) outStatus;
- (void) outBuffer;
- });
- if (!transResult.isOk()) {
+ if (!mRemoteConnection->sync().isOk()) {
ALOGD("sync from client %lld failed: bufferpool process died.",
(long long)mConnectionId);
}
@@ -616,12 +602,12 @@
mCache.decActive_l();
} else {
// should not happen!
- ALOGW("client %lld cache release status inconsitent!",
+ ALOGW("client %lld cache release status inconsistent!",
(long long)mConnectionId);
}
} else {
// should not happen!
- ALOGW("client %lld cache status inconsitent!", (long long)mConnectionId);
+ ALOGW("client %lld cache status inconsistent!", (long long)mConnectionId);
}
}
mReleasing.mReleasedIds.clear();
@@ -673,8 +659,8 @@
// should have mCache.mLock
void BufferPoolClient::Impl::evictCaches(bool clearCache) {
- int64_t now = getTimestampNow();
- if (now >= mLastEvictCacheUs + kCacheTtlUs ||
+ int64_t now = ::android::elapsedRealtime();
+ if (now >= mLastEvictCacheMs + kCacheTtlMs ||
clearCache || mCache.cachedBufferCount() > kMaxCachedBufferCount) {
size_t evicted = 0;
for (auto it = mCache.mBuffers.begin(); it != mCache.mBuffers.end();) {
@@ -688,7 +674,7 @@
}
ALOGV("cache count %lld : total %zu, active %d, evicted %zu",
(long long)mConnectionId, mCache.mBuffers.size(), mCache.mActive, evicted);
- mLastEvictCacheUs = now;
+ mLastEvictCacheMs = now;
}
}
@@ -701,7 +687,7 @@
ALOGV("cache invalidated %lld : buffer %u",
(long long)mConnectionId, id);
} else {
- ALOGW("Inconsitent invalidation %lld : activer buffer!! %u",
+ ALOGW("Inconsistent invalidation %lld : activer buffer!! %u",
(long long)mConnectionId, (unsigned int)id);
}
break;
@@ -735,12 +721,12 @@
(long long)mConnectionId, invalidated);
}
-ResultStatus BufferPoolClient::Impl::allocateBufferHandle(
+BufferPoolStatus BufferPoolClient::Impl::allocateBufferHandle(
const std::vector<uint8_t>& params, BufferId *bufferId,
native_handle_t** handle) {
if (mLocalConnection) {
const native_handle_t* allocHandle = nullptr;
- ResultStatus status = mLocalConnection->allocate(
+ BufferPoolStatus status = mLocalConnection->allocate(
params, bufferId, &allocHandle);
if (status == ResultStatus::OK) {
*handle = native_handle_clone(allocHandle);
@@ -753,37 +739,38 @@
return ResultStatus::CRITICAL_ERROR;
}
-ResultStatus BufferPoolClient::Impl::fetchBufferHandle(
+BufferPoolStatus BufferPoolClient::Impl::fetchBufferHandle(
TransactionId transactionId, BufferId bufferId,
native_handle_t **handle) {
- sp<IConnection> connection;
+ std::shared_ptr<IConnection> connection;
if (mLocal) {
connection = mLocalConnection;
} else {
connection = mRemoteConnection;
}
- ResultStatus status;
- Return<void> transResult = connection->fetch(
- transactionId, bufferId,
- [&status, &handle]
- (ResultStatus outStatus, Buffer outBuffer) {
- status = outStatus;
- if (status == ResultStatus::OK) {
- *handle = native_handle_clone(
- outBuffer.buffer.getNativeHandle());
- }
- });
- return transResult.isOk() ? status : ResultStatus::CRITICAL_ERROR;
+ std::vector<FetchInfo> infos;
+ std::vector<FetchResult> results;
+ infos.emplace_back(FetchInfo{ToAidl(transactionId), ToAidl(bufferId)});
+ ndk::ScopedAStatus status = connection->fetch(infos, &results);
+ if (!status.isOk()) {
+ BufferPoolStatus svcSpecific = status.getServiceSpecificError();
+ return svcSpecific ? svcSpecific : ResultStatus::CRITICAL_ERROR;
+ }
+ if (results[0].getTag() == FetchResult::buffer) {
+ *handle = ::android::dupFromAidl(results[0].get<FetchResult::buffer>().buffer);
+ return ResultStatus::OK;
+ }
+ return results[0].get<FetchResult::failure>();
}
-BufferPoolClient::BufferPoolClient(const sp<Accessor> &accessor,
- const sp<IObserver> &observer) {
+BufferPoolClient::BufferPoolClient(const std::shared_ptr<Accessor> &accessor,
+ const std::shared_ptr<IObserver> &observer) {
mImpl = std::make_shared<Impl>(accessor, observer);
}
-BufferPoolClient::BufferPoolClient(const sp<IAccessor> &accessor,
- const sp<IObserver> &observer) {
+BufferPoolClient::BufferPoolClient(const std::shared_ptr<IAccessor> &accessor,
+ const std::shared_ptr<IObserver> &observer) {
mImpl = std::make_shared<Impl>(accessor, observer);
}
@@ -799,12 +786,12 @@
return mImpl && mImpl->isLocal();
}
-bool BufferPoolClient::isActive(int64_t *lastTransactionUs, bool clearCache) {
+bool BufferPoolClient::isActive(int64_t *lastTransactionMs, bool clearCache) {
if (!isValid()) {
- *lastTransactionUs = 0;
+ *lastTransactionMs = 0;
return false;
}
- return mImpl->isActive(lastTransactionUs, clearCache);
+ return mImpl->isActive(lastTransactionMs, clearCache);
}
ConnectionId BufferPoolClient::getConnectionId() {
@@ -814,7 +801,7 @@
return -1;
}
-ResultStatus BufferPoolClient::getAccessor(sp<IAccessor> *accessor) {
+BufferPoolStatus BufferPoolClient::getAccessor(std::shared_ptr<IAccessor> *accessor) {
if (isValid()) {
*accessor = mImpl->getAccessor();
return ResultStatus::OK;
@@ -829,14 +816,14 @@
}
}
-ResultStatus BufferPoolClient::flush() {
+BufferPoolStatus BufferPoolClient::flush() {
if (isValid()) {
return mImpl->flush();
}
return ResultStatus::CRITICAL_ERROR;
}
-ResultStatus BufferPoolClient::allocate(
+BufferPoolStatus BufferPoolClient::allocate(
const std::vector<uint8_t> ¶ms,
native_handle_t **handle,
std::shared_ptr<BufferPoolData> *buffer) {
@@ -846,31 +833,26 @@
return ResultStatus::CRITICAL_ERROR;
}
-ResultStatus BufferPoolClient::receive(
- TransactionId transactionId, BufferId bufferId, int64_t timestampUs,
+BufferPoolStatus BufferPoolClient::receive(
+ TransactionId transactionId, BufferId bufferId, int64_t timestampMs,
native_handle_t **handle, std::shared_ptr<BufferPoolData> *buffer) {
if (isValid()) {
- return mImpl->receive(transactionId, bufferId, timestampUs, handle, buffer);
+ return mImpl->receive(transactionId, bufferId, timestampMs, handle, buffer);
}
return ResultStatus::CRITICAL_ERROR;
}
-ResultStatus BufferPoolClient::postSend(
+BufferPoolStatus BufferPoolClient::postSend(
ConnectionId receiverId,
const std::shared_ptr<BufferPoolData> &buffer,
TransactionId *transactionId,
- int64_t *timestampUs) {
+ int64_t *timestampMs) {
if (isValid()) {
bool result = mImpl->postSend(
- buffer->mId, receiverId, transactionId, timestampUs);
+ buffer->mId, receiverId, transactionId, timestampMs);
return result ? ResultStatus::OK : ResultStatus::CRITICAL_ERROR;
}
return ResultStatus::CRITICAL_ERROR;
}
-} // namespace implementation
-} // namespace V2_0
-} // namespace bufferpool
-} // namespace media
-} // namespace hardware
-} // namespace android
+} // namespace aidl::android::hardware::media::bufferpool2::implementation
diff --git a/media/bufferpool/aidl/default/BufferPoolClient.h b/media/bufferpool/aidl/default/BufferPoolClient.h
index e8d9ae6..80fd43e 100644
--- a/media/bufferpool/aidl/default/BufferPoolClient.h
+++ b/media/bufferpool/aidl/default/BufferPoolClient.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,29 +14,19 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_BUFFERPOOLCLIENT_H
-#define ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_BUFFERPOOLCLIENT_H
+#pragma once
#include <memory>
-#include <android/hardware/media/bufferpool/2.0/IAccessor.h>
-#include <android/hardware/media/bufferpool/2.0/IConnection.h>
-#include <android/hardware/media/bufferpool/2.0/IObserver.h>
-#include <bufferpool/BufferPoolTypes.h>
-#include <cutils/native_handle.h>
-#include "Accessor.h"
+#include <aidl/android/hardware/media/bufferpool2/IAccessor.h>
+#include <aidl/android/hardware/media/bufferpool2/IObserver.h>
+#include <bufferpool2/BufferPoolTypes.h>
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
-namespace V2_0 {
-namespace implementation {
+namespace aidl::android::hardware::media::bufferpool2::implementation {
-using ::android::hardware::media::bufferpool::V2_0::IAccessor;
-using ::android::hardware::media::bufferpool::V2_0::IConnection;
-using ::android::hardware::media::bufferpool::V2_0::IObserver;
-using ::android::hardware::media::bufferpool::V2_0::ResultStatus;
-using ::android::sp;
+using aidl::android::hardware::media::bufferpool2::IAccessor;
+using aidl::android::hardware::media::bufferpool2::IObserver;
+
+struct Accessor;
/**
* A buffer pool client for a buffer pool. For a specific buffer pool, at most
@@ -49,8 +39,8 @@
* Creates a buffer pool client from a local buffer pool
* (via ClientManager#create).
*/
- explicit BufferPoolClient(const sp<Accessor> &accessor,
- const sp<IObserver> &observer);
+ explicit BufferPoolClient(const std::shared_ptr<Accessor> &accessor,
+ const std::shared_ptr<IObserver> &observer);
/**
* Creates a buffer pool client from a remote buffer pool
@@ -58,8 +48,8 @@
* Note: A buffer pool client created with remote buffer pool cannot
* allocate a buffer.
*/
- explicit BufferPoolClient(const sp<IAccessor> &accessor,
- const sp<IObserver> &observer);
+ explicit BufferPoolClient(const std::shared_ptr<IAccessor> &accessor,
+ const std::shared_ptr<IObserver> &observer);
/** Destructs a buffer pool client. */
~BufferPoolClient();
@@ -69,30 +59,30 @@
bool isLocal();
- bool isActive(int64_t *lastTransactionUs, bool clearCache);
+ bool isActive(int64_t *lastTransactionMs, bool clearCache);
ConnectionId getConnectionId();
- ResultStatus getAccessor(sp<IAccessor> *accessor);
+ BufferPoolStatus getAccessor(std::shared_ptr<IAccessor> *accessor);
void receiveInvalidation(uint32_t msgId);
- ResultStatus flush();
+ BufferPoolStatus flush();
- ResultStatus allocate(const std::vector<uint8_t> ¶ms,
+ BufferPoolStatus allocate(const std::vector<uint8_t> ¶ms,
native_handle_t **handle,
std::shared_ptr<BufferPoolData> *buffer);
- ResultStatus receive(TransactionId transactionId,
+ BufferPoolStatus receive(TransactionId transactionId,
BufferId bufferId,
- int64_t timestampUs,
+ int64_t timestampMs,
native_handle_t **handle,
std::shared_ptr<BufferPoolData> *buffer);
- ResultStatus postSend(ConnectionId receiver,
+ BufferPoolStatus postSend(ConnectionId receiver,
const std::shared_ptr<BufferPoolData> &buffer,
TransactionId *transactionId,
- int64_t *timestampUs);
+ int64_t *timestampMs);
class Impl;
std::shared_ptr<Impl> mImpl;
@@ -101,11 +91,4 @@
friend struct Observer;
};
-} // namespace implementation
-} // namespace V2_0
-} // namespace bufferpool
-} // namespace media
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_BUFFERPOOLCLIENT_H
+} // namespace aidl::android::hardware::bufferpool2::implementation
diff --git a/media/bufferpool/aidl/default/BufferStatus.cpp b/media/bufferpool/aidl/default/BufferStatus.cpp
index 6937260..19caa1e 100644
--- a/media/bufferpool/aidl/default/BufferStatus.cpp
+++ b/media/bufferpool/aidl/default/BufferStatus.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,29 +14,17 @@
* limitations under the License.
*/
-#define LOG_TAG "BufferPoolStatus"
+#define LOG_TAG "AidlBufferPoolStatus"
//#define LOG_NDEBUG 0
#include <thread>
#include <time.h>
+#include <aidl/android/hardware/media/bufferpool2/BufferStatus.h>
#include "BufferStatus.h"
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
-namespace V2_0 {
-namespace implementation {
+namespace aidl::android::hardware::media::bufferpool2::implementation {
-int64_t getTimestampNow() {
- int64_t stamp;
- struct timespec ts;
- // TODO: CLOCK_MONOTONIC_COARSE?
- clock_gettime(CLOCK_MONOTONIC, &ts);
- stamp = ts.tv_nsec / 1000;
- stamp += (ts.tv_sec * 1000000LL);
- return stamp;
-}
+using aidl::android::hardware::media::bufferpool2::BufferStatus;
bool isMessageLater(uint32_t curMsgId, uint32_t prevMsgId) {
return curMsgId != prevMsgId && curMsgId - prevMsgId < prevMsgId - curMsgId;
@@ -53,30 +41,26 @@
static constexpr int kNumElementsInQueue = 1024*16;
static constexpr int kMinElementsToSyncInQueue = 128;
-ResultStatus BufferStatusObserver::open(
- ConnectionId id, const StatusDescriptor** fmqDescPtr) {
+BufferPoolStatus BufferStatusObserver::open(
+ ConnectionId id, StatusDescriptor* fmqDescPtr) {
if (mBufferStatusQueues.find(id) != mBufferStatusQueues.end()) {
- // TODO: id collision log?
+ ALOGE("connection id collision %lld", (unsigned long long)id);
return ResultStatus::CRITICAL_ERROR;
}
- std::unique_ptr<BufferStatusQueue> queue =
- std::make_unique<BufferStatusQueue>(kNumElementsInQueue);
+ auto queue = std::make_unique<BufferStatusQueue>(kNumElementsInQueue);
if (!queue || queue->isValid() == false) {
- *fmqDescPtr = nullptr;
return ResultStatus::NO_MEMORY;
- } else {
- *fmqDescPtr = queue->getDesc();
}
+ *fmqDescPtr = queue->dupeDesc();
auto result = mBufferStatusQueues.insert(
std::make_pair(id, std::move(queue)));
if (!result.second) {
- *fmqDescPtr = nullptr;
return ResultStatus::NO_MEMORY;
}
return ResultStatus::OK;
}
-ResultStatus BufferStatusObserver::close(ConnectionId id) {
+BufferPoolStatus BufferStatusObserver::close(ConnectionId id) {
if (mBufferStatusQueues.find(id) == mBufferStatusQueues.end()) {
return ResultStatus::CRITICAL_ERROR;
}
@@ -90,7 +74,7 @@
size_t avail = it->second->availableToRead();
while (avail > 0) {
if (!it->second->read(&message, 1)) {
- // Since avaliable # of reads are already confirmed,
+ // Since available # of reads are already confirmed,
// this should not happen.
// TODO: error handling (spurious client?)
ALOGW("FMQ message cannot be read from %lld", (long long)it->first);
@@ -105,8 +89,7 @@
BufferStatusChannel::BufferStatusChannel(
const StatusDescriptor &fmqDesc) {
- std::unique_ptr<BufferStatusQueue> queue =
- std::make_unique<BufferStatusQueue>(fmqDesc);
+ auto queue = std::make_unique<BufferStatusQueue>(fmqDesc);
if (!queue || queue->isValid() == false) {
mValid = false;
return;
@@ -136,11 +119,11 @@
BufferStatusMessage message;
for (size_t i = 0 ; i < avail; ++i) {
BufferId id = pending.front();
- message.newStatus = BufferStatus::NOT_USED;
+ message.status = BufferStatus::NOT_USED;
message.bufferId = id;
message.connectionId = connectionId;
if (!mBufferStatusQueue->write(&message, 1)) {
- // Since avaliable # of writes are already confirmed,
+ // Since available # of writes are already confirmed,
// this should not happen.
// TODO: error handing?
ALOGW("FMQ message cannot be sent from %lld", (long long)connectionId);
@@ -160,11 +143,11 @@
size_t avail = mBufferStatusQueue->availableToWrite();
if (avail > 0) {
BufferStatusMessage message;
- message.newStatus = BufferStatus::INVALIDATION_ACK;
+ message.status = BufferStatus::INVALIDATION_ACK;
message.bufferId = invalidateId;
message.connectionId = connectionId;
if (!mBufferStatusQueue->write(&message, 1)) {
- // Since avaliable # of writes are already confirmed,
+ // Since available # of writes are already confirmed,
// this should not happen.
// TODO: error handing?
ALOGW("FMQ message cannot be sent from %lld", (long long)connectionId);
@@ -186,11 +169,11 @@
BufferStatusMessage release, message;
for (size_t i = 0; i < numPending; ++i) {
BufferId id = pending.front();
- release.newStatus = BufferStatus::NOT_USED;
+ release.status = BufferStatus::NOT_USED;
release.bufferId = id;
release.connectionId = connectionId;
if (!mBufferStatusQueue->write(&release, 1)) {
- // Since avaliable # of writes are already confirmed,
+ // Since available # of writes are already confirmed,
// this should not happen.
// TODO: error handling?
ALOGW("FMQ message cannot be sent from %lld", (long long)connectionId);
@@ -201,13 +184,13 @@
}
message.transactionId = transactionId;
message.bufferId = bufferId;
- message.newStatus = status;
+ message.status = status;
message.connectionId = connectionId;
message.targetConnectionId = targetId;
// TODO : timesatamp
message.timestampUs = 0;
if (!mBufferStatusQueue->write(&message, 1)) {
- // Since avaliable # of writes are already confirmed,
+ // Since available # of writes are already confirmed,
// this should not happen.
ALOGW("FMQ message cannot be sent from %lld", (long long)connectionId);
return false;
@@ -276,12 +259,11 @@
return mValid;
}
-void BufferInvalidationChannel::getDesc(const InvalidationDescriptor **fmqDescPtr) {
+void BufferInvalidationChannel::getDesc(InvalidationDescriptor *fmqDescPtr) {
if (mValid) {
- *fmqDescPtr = mBufferInvalidationQueue->getDesc();
- } else {
- *fmqDescPtr = nullptr;
+ *fmqDescPtr = mBufferInvalidationQueue->dupeDesc();
}
+ // TODO: writing invalid descriptor?
}
void BufferInvalidationChannel::postInvalidation(
@@ -295,10 +277,5 @@
mBufferInvalidationQueue->write(&message);
}
-} // namespace implementation
-} // namespace V2_0
-} // namespace bufferpool
-} // namespace media
-} // namespace hardware
-} // namespace android
+} // namespace ::aidl::android::hardware::media::bufferpool2::implementation
diff --git a/media/bufferpool/aidl/default/BufferStatus.h b/media/bufferpool/aidl/default/BufferStatus.h
index fa65838..3dd92f4 100644
--- a/media/bufferpool/aidl/default/BufferStatus.h
+++ b/media/bufferpool/aidl/default/BufferStatus.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,28 +14,16 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_BUFFERSTATUS_H
-#define ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_BUFFERSTATUS_H
+#pragma once
-#include <android/hardware/media/bufferpool/2.0/types.h>
-#include <bufferpool/BufferPoolTypes.h>
-#include <fmq/MessageQueue.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
+#include <bufferpool2/BufferPoolTypes.h>
+#include <map>
#include <memory>
#include <mutex>
#include <vector>
#include <list>
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
-namespace V2_0 {
-namespace implementation {
-
-/** Returns monotonic timestamp in Us since fixed point in time. */
-int64_t getTimestampNow();
+namespace aidl::android::hardware::media::bufferpool2::implementation {
bool isMessageLater(uint32_t curMsgId, uint32_t prevMsgId);
@@ -55,13 +43,13 @@
* connection(client).
*
* @param connectionId connection Id of the specified client.
- * @param fmqDescPtr double ptr of created FMQ's descriptor.
+ * @param fmqDescPtr ptr of created FMQ's descriptor.
*
* @return OK if FMQ is created successfully.
* NO_MEMORY when there is no memory.
* CRITICAL_ERROR otherwise.
*/
- ResultStatus open(ConnectionId id, const StatusDescriptor** fmqDescPtr);
+ BufferPoolStatus open(ConnectionId id, StatusDescriptor* _Nonnull fmqDescPtr);
/** Closes a buffer status message FMQ for the specified
* connection(client).
@@ -71,7 +59,7 @@
* @return OK if the specified connection is closed successfully.
* CRITICAL_ERROR otherwise.
*/
- ResultStatus close(ConnectionId id);
+ BufferPoolStatus close(ConnectionId id);
/** Retrieves all pending FMQ buffer status messages from clients.
*
@@ -140,7 +128,7 @@
std::list<BufferId> &pending, std::list<BufferId> &posted);
/**
- * Posts a buffer invaliadation messge to the buffer pool.
+ * Posts a buffer invaliadation message to the buffer pool.
*
* @param connectionId connection Id of the client.
* @param invalidateId invalidation ack to the buffer pool.
@@ -152,7 +140,7 @@
void postBufferInvalidateAck(
ConnectionId connectionId,
uint32_t invalidateId,
- bool *invalidated);
+ bool* _Nonnull invalidated);
};
/**
@@ -179,7 +167,7 @@
*/
void getInvalidations(std::vector<BufferInvalidationMessage> &messages);
- /** Returns whether the FMQ is connected succesfully. */
+ /** Returns whether the FMQ is connected successfully. */
bool isValid();
};
@@ -199,16 +187,16 @@
*/
BufferInvalidationChannel();
- /** Returns whether the FMQ is connected succesfully. */
+ /** Returns whether the FMQ is connected successfully. */
bool isValid();
/**
* Retrieves the descriptor of a buffer invalidation FMQ. the descriptor may
* be passed to the client for buffer invalidation handling.
*
- * @param fmqDescPtr double ptr of created FMQ's descriptor.
+ * @param fmqDescPtr ptr of created FMQ's descriptor.
*/
- void getDesc(const InvalidationDescriptor **fmqDescPtr);
+ void getDesc(InvalidationDescriptor* _Nonnull fmqDescPtr);
/** Posts a buffer invalidation for invalidated buffers.
*
@@ -220,11 +208,4 @@
void postInvalidation(uint32_t msgId, BufferId fromId, BufferId toId);
};
-} // namespace implementation
-} // namespace V2_0
-} // namespace bufferpool
-} // namespace media
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_BUFFERSTATUS_H
+} // namespace aidl::android::hardware::media::bufferpool2::implementation
diff --git a/media/bufferpool/aidl/default/ClientManager.cpp b/media/bufferpool/aidl/default/ClientManager.cpp
index 54a20b9..de1db50 100644
--- a/media/bufferpool/aidl/default/ClientManager.cpp
+++ b/media/bufferpool/aidl/default/ClientManager.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,122 +13,74 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#define LOG_TAG "BufferPoolManager"
+#define LOG_TAG "AidlBufferPoolMgr"
//#define LOG_NDEBUG 0
-#include <bufferpool/ClientManager.h>
-#include <hidl/HidlTransportSupport.h>
+#include <aidl/android/hardware/media/bufferpool2/ResultStatus.h>
+#include <bufferpool2/ClientManager.h>
+
#include <sys/types.h>
-#include <time.h>
+#include <utils/SystemClock.h>
#include <unistd.h>
#include <utils/Log.h>
+
+#include <chrono>
+
#include "BufferPoolClient.h"
#include "Observer.h"
#include "Accessor.h"
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
-namespace V2_0 {
-namespace implementation {
+namespace aidl::android::hardware::media::bufferpool2::implementation {
-static constexpr int64_t kRegisterTimeoutUs = 500000; // 0.5 sec
-static constexpr int64_t kCleanUpDurationUs = 1000000; // TODO: 1 sec tune
-static constexpr int64_t kClientTimeoutUs = 5000000; // TODO: 5 secs tune
+using namespace std::chrono_literals;
-/**
- * The holder of the cookie of remote IClientManager.
- * The cookie is process locally unique for each IClientManager.
- * (The cookie is used to notify death of clients to bufferpool process.)
- */
-class ClientManagerCookieHolder {
-public:
- /**
- * Creates a cookie holder for remote IClientManager(s).
- */
- ClientManagerCookieHolder();
+using Registration = aidl::android::hardware::media::bufferpool2::IClientManager::Registration;
+using aidl::android::hardware::media::bufferpool2::ResultStatus;
- /**
- * Gets a cookie for a remote IClientManager.
- *
- * @param manager the specified remote IClientManager.
- * @param added true when the specified remote IClientManager is added
- * newly, false otherwise.
- *
- * @return the process locally unique cookie for the specified IClientManager.
- */
- uint64_t getCookie(const sp<IClientManager> &manager, bool *added);
-
-private:
- uint64_t mSeqId;
- std::mutex mLock;
- std::list<std::pair<const wp<IClientManager>, uint64_t>> mManagers;
-};
-
-ClientManagerCookieHolder::ClientManagerCookieHolder() : mSeqId(0){}
-
-uint64_t ClientManagerCookieHolder::getCookie(
- const sp<IClientManager> &manager,
- bool *added) {
- std::lock_guard<std::mutex> lock(mLock);
- for (auto it = mManagers.begin(); it != mManagers.end();) {
- const sp<IClientManager> key = it->first.promote();
- if (key) {
- if (interfacesEqual(key, manager)) {
- *added = false;
- return it->second;
- }
- ++it;
- } else {
- it = mManagers.erase(it);
- }
- }
- uint64_t id = mSeqId++;
- *added = true;
- mManagers.push_back(std::make_pair(manager, id));
- return id;
-}
+static constexpr int64_t kRegisterTimeoutMs = 500; // 0.5 sec
+static constexpr int64_t kCleanUpDurationMs = 1000; // TODO: 1 sec tune
+static constexpr int64_t kClientTimeoutMs = 5000; // TODO: 5 secs tune
class ClientManager::Impl {
public:
Impl();
// BnRegisterSender
- ResultStatus registerSender(const sp<IAccessor> &accessor,
- ConnectionId *pConnectionId);
+ BufferPoolStatus registerSender(const std::shared_ptr<IAccessor> &accessor,
+ Registration *pRegistration);
// BpRegisterSender
- ResultStatus registerSender(const sp<IClientManager> &receiver,
+ BufferPoolStatus registerSender(const std::shared_ptr<IClientManager> &receiver,
ConnectionId senderId,
- ConnectionId *receiverId);
+ ConnectionId *receiverId,
+ bool *isNew);
- ResultStatus create(const std::shared_ptr<BufferPoolAllocator> &allocator,
+ BufferPoolStatus create(const std::shared_ptr<BufferPoolAllocator> &allocator,
ConnectionId *pConnectionId);
- ResultStatus close(ConnectionId connectionId);
+ BufferPoolStatus close(ConnectionId connectionId);
- ResultStatus flush(ConnectionId connectionId);
+ BufferPoolStatus flush(ConnectionId connectionId);
- ResultStatus allocate(ConnectionId connectionId,
+ BufferPoolStatus allocate(ConnectionId connectionId,
const std::vector<uint8_t> ¶ms,
native_handle_t **handle,
std::shared_ptr<BufferPoolData> *buffer);
- ResultStatus receive(ConnectionId connectionId,
+ BufferPoolStatus receive(ConnectionId connectionId,
TransactionId transactionId,
BufferId bufferId,
- int64_t timestampUs,
+ int64_t timestampMs,
native_handle_t **handle,
std::shared_ptr<BufferPoolData> *buffer);
- ResultStatus postSend(ConnectionId receiverId,
+ BufferPoolStatus postSend(ConnectionId receiverId,
const std::shared_ptr<BufferPoolData> &buffer,
TransactionId *transactionId,
- int64_t *timestampUs);
+ int64_t *timestampMs);
- ResultStatus getAccessor(ConnectionId connectionId,
- sp<IAccessor> *accessor);
+ BufferPoolStatus getAccessor(ConnectionId connectionId,
+ std::shared_ptr<IAccessor> *accessor);
void cleanUp(bool clearCache = false);
@@ -139,13 +91,13 @@
// This lock is held for brief duration.
// Blocking operation is not performed while holding the lock.
std::mutex mMutex;
- std::list<std::pair<const wp<IAccessor>, const std::weak_ptr<BufferPoolClient>>>
+ std::list<std::pair<const std::weak_ptr<IAccessor>, const std::weak_ptr<BufferPoolClient>>>
mClients;
std::condition_variable mConnectCv;
bool mConnecting;
- int64_t mLastCleanUpUs;
+ int64_t mLastCleanUpMs;
- ClientCache() : mConnecting(false), mLastCleanUpUs(getTimestampNow()) {}
+ ClientCache() : mConnecting(false), mLastCleanUpMs(::android::elapsedRealtime()) {}
} mCache;
// Active clients which can be retrieved via ConnectionId
@@ -157,30 +109,31 @@
mClients;
} mActive;
- sp<Observer> mObserver;
-
- ClientManagerCookieHolder mRemoteClientCookies;
+ std::shared_ptr<Observer> mObserver;
};
ClientManager::Impl::Impl()
- : mObserver(new Observer()) {}
+ : mObserver(::ndk::SharedRefBase::make<Observer>()) {}
-ResultStatus ClientManager::Impl::registerSender(
- const sp<IAccessor> &accessor, ConnectionId *pConnectionId) {
+BufferPoolStatus ClientManager::Impl::registerSender(
+ const std::shared_ptr<IAccessor> &accessor, Registration *pRegistration) {
cleanUp();
- int64_t timeoutUs = getTimestampNow() + kRegisterTimeoutUs;
+ int64_t timeoutMs = ::android::elapsedRealtime() + kRegisterTimeoutMs;
do {
std::unique_lock<std::mutex> lock(mCache.mMutex);
for (auto it = mCache.mClients.begin(); it != mCache.mClients.end(); ++it) {
- sp<IAccessor> sAccessor = it->first.promote();
- if (sAccessor && interfacesEqual(sAccessor, accessor)) {
+ std::shared_ptr<IAccessor> sAccessor = it->first.lock();
+ if (sAccessor && sAccessor.get() == accessor.get()) {
const std::shared_ptr<BufferPoolClient> client = it->second.lock();
if (client) {
std::lock_guard<std::mutex> lock(mActive.mMutex);
- *pConnectionId = client->getConnectionId();
- if (mActive.mClients.find(*pConnectionId) != mActive.mClients.end()) {
- ALOGV("register existing connection %lld", (long long)*pConnectionId);
- return ResultStatus::ALREADY_EXISTS;
+ pRegistration->connectionId = client->getConnectionId();
+ if (mActive.mClients.find(pRegistration->connectionId)
+ != mActive.mClients.end()) {
+ ALOGV("register existing connection %lld",
+ (long long)pRegistration->connectionId);
+ pRegistration->isNew = false;
+ return ResultStatus::OK;
}
}
mCache.mClients.erase(it);
@@ -190,7 +143,7 @@
if (!mCache.mConnecting) {
mCache.mConnecting = true;
lock.unlock();
- ResultStatus result = ResultStatus::OK;
+ BufferPoolStatus result = ResultStatus::OK;
const std::shared_ptr<BufferPoolClient> client =
std::make_shared<BufferPoolClient>(accessor, mObserver);
lock.lock();
@@ -209,26 +162,27 @@
std::lock_guard<std::mutex> lock(mActive.mMutex);
mActive.mClients.insert(std::make_pair(conId, client));
}
- *pConnectionId = conId;
- ALOGV("register new connection %lld", (long long)*pConnectionId);
+ pRegistration->connectionId = conId;
+ pRegistration->isNew = true;
+ ALOGV("register new connection %lld", (long long)conId);
}
mCache.mConnecting = false;
lock.unlock();
mCache.mConnectCv.notify_all();
return result;
}
- mCache.mConnectCv.wait_for(
- lock, std::chrono::microseconds(kRegisterTimeoutUs));
- } while (getTimestampNow() < timeoutUs);
+ mCache.mConnectCv.wait_for(lock, kRegisterTimeoutMs*1ms);
+ } while (::android::elapsedRealtime() < timeoutMs);
// TODO: return timeout error
return ResultStatus::CRITICAL_ERROR;
}
-ResultStatus ClientManager::Impl::registerSender(
- const sp<IClientManager> &receiver,
+BufferPoolStatus ClientManager::Impl::registerSender(
+ const std::shared_ptr<IClientManager> &receiver,
ConnectionId senderId,
- ConnectionId *receiverId) {
- sp<IAccessor> accessor;
+ ConnectionId *receiverId,
+ bool *isNew) {
+ std::shared_ptr<IAccessor> accessor;
bool local = false;
{
std::lock_guard<std::mutex> lock(mActive.mMutex);
@@ -239,38 +193,32 @@
it->second->getAccessor(&accessor);
local = it->second->isLocal();
}
- ResultStatus rs = ResultStatus::CRITICAL_ERROR;
if (accessor) {
- Return<void> transResult = receiver->registerSender(
- accessor,
- [&rs, receiverId](
- ResultStatus status,
- int64_t connectionId) {
- rs = status;
- *receiverId = connectionId;
- });
- if (!transResult.isOk()) {
+ Registration registration;
+ ::ndk::ScopedAStatus status = receiver->registerSender(accessor, ®istration);
+ if (!status.isOk()) {
return ResultStatus::CRITICAL_ERROR;
- } else if (local && rs == ResultStatus::OK) {
- sp<ConnectionDeathRecipient> recipient = Accessor::getConnectionDeathRecipient();
+ } else if (local) {
+ std::shared_ptr<ConnectionDeathRecipient> recipient =
+ Accessor::getConnectionDeathRecipient();
if (recipient) {
ALOGV("client death recipient registered %lld", (long long)*receiverId);
- bool added;
- uint64_t cookie = mRemoteClientCookies.getCookie(receiver, &added);
- recipient->addCookieToConnection(cookie, *receiverId);
- if (added) {
- Return<bool> transResult = receiver->linkToDeath(recipient, cookie);
- }
+ recipient->addCookieToConnection(receiver->asBinder().get(), *receiverId);
+ AIBinder_linkToDeath(receiver->asBinder().get(), recipient->getRecipient(),
+ receiver->asBinder().get());
}
}
+ *receiverId = registration.connectionId;
+ *isNew = registration.isNew;
+ return ResultStatus::OK;
}
- return rs;
+ return ResultStatus::CRITICAL_ERROR;
}
-ResultStatus ClientManager::Impl::create(
+BufferPoolStatus ClientManager::Impl::create(
const std::shared_ptr<BufferPoolAllocator> &allocator,
ConnectionId *pConnectionId) {
- const sp<Accessor> accessor = new Accessor(allocator);
+ std::shared_ptr<Accessor> accessor = ::ndk::SharedRefBase::make<Accessor>(allocator);
if (!accessor || !accessor->isValid()) {
return ResultStatus::CRITICAL_ERROR;
}
@@ -300,19 +248,19 @@
return ResultStatus::OK;
}
-ResultStatus ClientManager::Impl::close(ConnectionId connectionId) {
+BufferPoolStatus ClientManager::Impl::close(ConnectionId connectionId) {
std::unique_lock<std::mutex> lock1(mCache.mMutex);
std::unique_lock<std::mutex> lock2(mActive.mMutex);
auto it = mActive.mClients.find(connectionId);
if (it != mActive.mClients.end()) {
- sp<IAccessor> accessor;
+ std::shared_ptr<IAccessor> accessor;
it->second->getAccessor(&accessor);
std::shared_ptr<BufferPoolClient> closing = it->second;
mActive.mClients.erase(connectionId);
for (auto cit = mCache.mClients.begin(); cit != mCache.mClients.end();) {
// clean up dead client caches
- sp<IAccessor> cAccessor = cit->first.promote();
- if (!cAccessor || (accessor && interfacesEqual(cAccessor, accessor))) {
+ std::shared_ptr<IAccessor> cAccessor = cit->first.lock();
+ if (!cAccessor || (accessor && cAccessor.get() == accessor.get())) {
cit = mCache.mClients.erase(cit);
} else {
cit++;
@@ -326,7 +274,7 @@
return ResultStatus::NOT_FOUND;
}
-ResultStatus ClientManager::Impl::flush(ConnectionId connectionId) {
+BufferPoolStatus ClientManager::Impl::flush(ConnectionId connectionId) {
std::shared_ptr<BufferPoolClient> client;
{
std::lock_guard<std::mutex> lock(mActive.mMutex);
@@ -339,7 +287,7 @@
return client->flush();
}
-ResultStatus ClientManager::Impl::allocate(
+BufferPoolStatus ClientManager::Impl::allocate(
ConnectionId connectionId, const std::vector<uint8_t> ¶ms,
native_handle_t **handle, std::shared_ptr<BufferPoolData> *buffer) {
std::shared_ptr<BufferPoolClient> client;
@@ -353,7 +301,7 @@
}
#ifdef BUFFERPOOL_CLONE_HANDLES
native_handle_t *origHandle;
- ResultStatus res = client->allocate(params, &origHandle, buffer);
+ BufferPoolStatus res = client->allocate(params, &origHandle, buffer);
if (res != ResultStatus::OK) {
return res;
}
@@ -368,9 +316,9 @@
#endif
}
-ResultStatus ClientManager::Impl::receive(
+BufferPoolStatus ClientManager::Impl::receive(
ConnectionId connectionId, TransactionId transactionId,
- BufferId bufferId, int64_t timestampUs,
+ BufferId bufferId, int64_t timestampMs,
native_handle_t **handle, std::shared_ptr<BufferPoolData> *buffer) {
std::shared_ptr<BufferPoolClient> client;
{
@@ -383,8 +331,8 @@
}
#ifdef BUFFERPOOL_CLONE_HANDLES
native_handle_t *origHandle;
- ResultStatus res = client->receive(
- transactionId, bufferId, timestampUs, &origHandle, buffer);
+ BufferPoolStatus res = client->receive(
+ transactionId, bufferId, timestampMs, &origHandle, buffer);
if (res != ResultStatus::OK) {
return res;
}
@@ -395,13 +343,13 @@
}
return ResultStatus::OK;
#else
- return client->receive(transactionId, bufferId, timestampUs, handle, buffer);
+ return client->receive(transactionId, bufferId, timestampMs, handle, buffer);
#endif
}
-ResultStatus ClientManager::Impl::postSend(
+BufferPoolStatus ClientManager::Impl::postSend(
ConnectionId receiverId, const std::shared_ptr<BufferPoolData> &buffer,
- TransactionId *transactionId, int64_t *timestampUs) {
+ TransactionId *transactionId, int64_t *timestampMs) {
ConnectionId connectionId = buffer->mConnectionId;
std::shared_ptr<BufferPoolClient> client;
{
@@ -412,11 +360,11 @@
}
client = it->second;
}
- return client->postSend(receiverId, buffer, transactionId, timestampUs);
+ return client->postSend(receiverId, buffer, transactionId, timestampMs);
}
-ResultStatus ClientManager::Impl::getAccessor(
- ConnectionId connectionId, sp<IAccessor> *accessor) {
+BufferPoolStatus ClientManager::Impl::getAccessor(
+ ConnectionId connectionId, std::shared_ptr<IAccessor> *accessor) {
std::shared_ptr<BufferPoolClient> client;
{
std::lock_guard<std::mutex> lock(mActive.mMutex);
@@ -430,16 +378,16 @@
}
void ClientManager::Impl::cleanUp(bool clearCache) {
- int64_t now = getTimestampNow();
- int64_t lastTransactionUs;
+ int64_t now = ::android::elapsedRealtime();
+ int64_t lastTransactionMs;
std::lock_guard<std::mutex> lock1(mCache.mMutex);
- if (clearCache || mCache.mLastCleanUpUs + kCleanUpDurationUs < now) {
+ if (clearCache || mCache.mLastCleanUpMs + kCleanUpDurationMs < now) {
std::lock_guard<std::mutex> lock2(mActive.mMutex);
int cleaned = 0;
for (auto it = mActive.mClients.begin(); it != mActive.mClients.end();) {
- if (!it->second->isActive(&lastTransactionUs, clearCache)) {
- if (lastTransactionUs + kClientTimeoutUs < now) {
- sp<IAccessor> accessor;
+ if (!it->second->isActive(&lastTransactionMs, clearCache)) {
+ if (lastTransactionMs + kClientTimeoutMs < now) {
+ std::shared_ptr<IAccessor> accessor;
it->second->getAccessor(&accessor);
it = mActive.mClients.erase(it);
++cleaned;
@@ -450,7 +398,7 @@
}
for (auto cit = mCache.mClients.begin(); cit != mCache.mClients.end();) {
// clean up dead client caches
- sp<IAccessor> cAccessor = cit->first.promote();
+ std::shared_ptr<IAccessor> cAccessor = cit->first.lock();
if (!cAccessor) {
cit = mCache.mClients.erase(cit);
} else {
@@ -458,30 +406,32 @@
}
}
ALOGV("# of cleaned connections: %d", cleaned);
- mCache.mLastCleanUpUs = now;
+ mCache.mLastCleanUpMs = now;
}
}
-// Methods from ::android::hardware::media::bufferpool::V2_0::IClientManager follow.
-Return<void> ClientManager::registerSender(const sp<::android::hardware::media::bufferpool::V2_0::IAccessor>& bufferPool, registerSender_cb _hidl_cb) {
+::ndk::ScopedAStatus ClientManager::registerSender(
+ const std::shared_ptr<IAccessor>& in_bufferPool, Registration* _aidl_return) {
+ BufferPoolStatus status = ResultStatus::CRITICAL_ERROR;
if (mImpl) {
- ConnectionId connectionId = -1;
- ResultStatus status = mImpl->registerSender(bufferPool, &connectionId);
- _hidl_cb(status, connectionId);
- } else {
- _hidl_cb(ResultStatus::CRITICAL_ERROR, -1);
+ status = mImpl->registerSender(in_bufferPool, _aidl_return);
}
- return Void();
+ if (status != ResultStatus::OK) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(status);
+ }
+ return ::ndk::ScopedAStatus::ok();
}
// Methods for local use.
-sp<ClientManager> ClientManager::sInstance;
+std::shared_ptr<ClientManager> ClientManager::sInstance;
std::mutex ClientManager::sInstanceLock;
-sp<ClientManager> ClientManager::getInstance() {
+std::shared_ptr<ClientManager> ClientManager::getInstance() {
std::lock_guard<std::mutex> lock(sInstanceLock);
if (!sInstance) {
- sInstance = new ClientManager();
+ sInstance = ::ndk::SharedRefBase::make<ClientManager>();
+ // TODO: configure thread count for threadpool properly
+ // after b/261652496 is resolved.
}
Accessor::createInvalidator();
Accessor::createEvictor();
@@ -493,7 +443,7 @@
ClientManager::~ClientManager() {
}
-ResultStatus ClientManager::create(
+BufferPoolStatus ClientManager::create(
const std::shared_ptr<BufferPoolAllocator> &allocator,
ConnectionId *pConnectionId) {
if (mImpl) {
@@ -502,31 +452,32 @@
return ResultStatus::CRITICAL_ERROR;
}
-ResultStatus ClientManager::registerSender(
- const sp<IClientManager> &receiver,
+BufferPoolStatus ClientManager::registerSender(
+ const std::shared_ptr<IClientManager> &receiver,
ConnectionId senderId,
- ConnectionId *receiverId) {
+ ConnectionId *receiverId,
+ bool *isNew) {
if (mImpl) {
- return mImpl->registerSender(receiver, senderId, receiverId);
+ return mImpl->registerSender(receiver, senderId, receiverId, isNew);
}
return ResultStatus::CRITICAL_ERROR;
}
-ResultStatus ClientManager::close(ConnectionId connectionId) {
+BufferPoolStatus ClientManager::close(ConnectionId connectionId) {
if (mImpl) {
return mImpl->close(connectionId);
}
return ResultStatus::CRITICAL_ERROR;
}
-ResultStatus ClientManager::flush(ConnectionId connectionId) {
+BufferPoolStatus ClientManager::flush(ConnectionId connectionId) {
if (mImpl) {
return mImpl->flush(connectionId);
}
return ResultStatus::CRITICAL_ERROR;
}
-ResultStatus ClientManager::allocate(
+BufferPoolStatus ClientManager::allocate(
ConnectionId connectionId, const std::vector<uint8_t> ¶ms,
native_handle_t **handle, std::shared_ptr<BufferPoolData> *buffer) {
if (mImpl) {
@@ -535,22 +486,22 @@
return ResultStatus::CRITICAL_ERROR;
}
-ResultStatus ClientManager::receive(
+BufferPoolStatus ClientManager::receive(
ConnectionId connectionId, TransactionId transactionId,
- BufferId bufferId, int64_t timestampUs,
+ BufferId bufferId, int64_t timestampMs,
native_handle_t **handle, std::shared_ptr<BufferPoolData> *buffer) {
if (mImpl) {
return mImpl->receive(connectionId, transactionId, bufferId,
- timestampUs, handle, buffer);
+ timestampMs, handle, buffer);
}
return ResultStatus::CRITICAL_ERROR;
}
-ResultStatus ClientManager::postSend(
+BufferPoolStatus ClientManager::postSend(
ConnectionId receiverId, const std::shared_ptr<BufferPoolData> &buffer,
- TransactionId *transactionId, int64_t* timestampUs) {
+ TransactionId *transactionId, int64_t* timestampMs) {
if (mImpl && buffer) {
- return mImpl->postSend(receiverId, buffer, transactionId, timestampUs);
+ return mImpl->postSend(receiverId, buffer, transactionId, timestampMs);
}
return ResultStatus::CRITICAL_ERROR;
}
@@ -561,9 +512,4 @@
}
}
-} // namespace implementation
-} // namespace V2_0
-} // namespace bufferpool
-} // namespace media
-} // namespace hardware
-} // namespace android
+} // namespace ::aidl::android::hardware::media::bufferpool2::implementation
diff --git a/media/bufferpool/aidl/default/Connection.cpp b/media/bufferpool/aidl/default/Connection.cpp
index 57d0c7e..53d350d 100644
--- a/media/bufferpool/aidl/default/Connection.cpp
+++ b/media/bufferpool/aidl/default/Connection.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,42 +13,63 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#define LOG_TAG "AidlBufferPoolCon"
+//#define LOG_NDEBUG 0
+
+#include <aidlcommonsupport/NativeHandle.h>
#include "Connection.h"
+#include "Accessor.h"
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
-namespace V2_0 {
-namespace implementation {
+namespace aidl::android::hardware::media::bufferpool2::implementation {
-// Methods from ::android::hardware::media::bufferpool::V2_0::IConnection follow.
-Return<void> Connection::fetch(uint64_t transactionId, uint32_t bufferId, fetch_cb _hidl_cb) {
- ResultStatus status = ResultStatus::CRITICAL_ERROR;
+using aidl::android::hardware::media::bufferpool2::ResultStatus;
+using Buffer = aidl::android::hardware::media::bufferpool2::Buffer;
+using FetchInfo = aidl::android::hardware::media::bufferpool2::IConnection::FetchInfo;
+using FetchResult = aidl::android::hardware::media::bufferpool2::IConnection::FetchResult;
+
+::ndk::ScopedAStatus Connection::fetch(const std::vector<FetchInfo>& in_fetchInfos,
+ std::vector<FetchResult>* _aidl_return) {
+ int success = 0;
+ int failure = 0;
if (mInitialized && mAccessor) {
- if (bufferId != SYNC_BUFFERID) {
- const native_handle_t *handle = nullptr;
- status = mAccessor->fetch(
- mConnectionId, transactionId, bufferId, &handle);
- if (status == ResultStatus::OK) {
- Buffer buffer = {};
- buffer.id = bufferId;
- buffer.buffer = handle;
- _hidl_cb(status, buffer);
- return Void();
+ for (auto it = in_fetchInfos.begin(); it != in_fetchInfos.end(); ++it) {
+ if (fetch(it->transactionId, it->bufferId, _aidl_return)) {
+ success++;
+ } else {
+ failure++;
}
- } else {
- mAccessor->cleanUp(false);
}
+ if (failure > 0) {
+ ALOGD("total fetch %d, failure %d", success + failure, failure);
+ }
+ return ::ndk::ScopedAStatus::ok();
}
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(ResultStatus::CRITICAL_ERROR);
+}
- Buffer buffer = {};
- buffer.id = 0;
- buffer.buffer = nullptr;
+::ndk::ScopedAStatus Connection::sync() {
+ if (mInitialized && mAccessor) {
+ mAccessor->cleanUp(false);
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
- _hidl_cb(status, buffer);
- return Void();
+
+bool Connection::fetch(TransactionId transactionId, BufferId bufferId,
+ std::vector<FetchResult> *result) {
+ BufferPoolStatus status = ResultStatus::CRITICAL_ERROR;
+ const native_handle_t *handle = nullptr;
+ status = mAccessor->fetch(
+ mConnectionId, transactionId, bufferId, &handle);
+ if (status == ResultStatus::OK) {
+ result->emplace_back(FetchResult::make<FetchResult::buffer>());
+ result->back().get<FetchResult::buffer>().id = bufferId;
+ result->back().get<FetchResult::buffer>().buffer = ::android::dupToAidl(handle);
+ return true;
+ }
+ result->emplace_back(FetchResult::make<FetchResult::failure>(status));
+ return false;
}
Connection::Connection() : mInitialized(false), mConnectionId(-1LL) {}
@@ -60,7 +81,7 @@
}
void Connection::initialize(
- const sp<Accessor>& accessor, ConnectionId connectionId) {
+ const std::shared_ptr<Accessor>& accessor, ConnectionId connectionId) {
if (!mInitialized) {
mAccessor = accessor;
mConnectionId = connectionId;
@@ -68,14 +89,14 @@
}
}
-ResultStatus Connection::flush() {
+BufferPoolStatus Connection::flush() {
if (mInitialized && mAccessor) {
return mAccessor->flush();
}
return ResultStatus::CRITICAL_ERROR;
}
-ResultStatus Connection::allocate(
+BufferPoolStatus Connection::allocate(
const std::vector<uint8_t> ¶ms, BufferId *bufferId,
const native_handle_t **handle) {
if (mInitialized && mAccessor) {
@@ -90,15 +111,4 @@
}
}
-// Methods from ::android::hidl::base::V1_0::IBase follow.
-
-//IConnection* HIDL_FETCH_IConnection(const char* /* name */) {
-// return new Connection();
-//}
-
-} // namespace implementation
-} // namespace V2_0
-} // namespace bufferpool
-} // namespace media
-} // namespace hardware
-} // namespace android
+} // namespace ::aidl::android::hardware::media::bufferpool2::implementation
diff --git a/media/bufferpool/aidl/default/Connection.h b/media/bufferpool/aidl/default/Connection.h
index 8507749..d8298af 100644
--- a/media/bufferpool/aidl/default/Connection.h
+++ b/media/bufferpool/aidl/default/Connection.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,39 +14,28 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_CONNECTION_H
-#define ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_CONNECTION_H
+#pragma once
-#include <android/hardware/media/bufferpool/2.0/IConnection.h>
-#include <bufferpool/BufferPoolTypes.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-#include "Accessor.h"
+#include <memory>
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
-namespace V2_0 {
-namespace implementation {
+#include <aidl/android/hardware/media/bufferpool2/BnConnection.h>
+#include <bufferpool2/BufferPoolTypes.h>
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::media::bufferpool::V2_0::implementation::Accessor;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
+namespace aidl::android::hardware::media::bufferpool2::implementation {
-struct Connection : public IConnection {
- // Methods from ::android::hardware::media::bufferpool::V2_0::IConnection follow.
- Return<void> fetch(uint64_t transactionId, uint32_t bufferId, fetch_cb _hidl_cb) override;
+struct Accessor;
+
+struct Connection : public BnConnection {
+ // Methods from ::aidl::android::hardware::media::bufferpool2::IConnection.
+ ::ndk::ScopedAStatus fetch(const std::vector<::aidl::android::hardware::media::bufferpool2::IConnection::FetchInfo>& in_fetchInfos, std::vector<::aidl::android::hardware::media::bufferpool2::IConnection::FetchResult>* _aidl_return) override;
+
+ // Methods from ::aidl::android::hardware::media::bufferpool2::IConnection.
+ ::ndk::ScopedAStatus sync() override;
/**
* Invalidates all buffers which are active and/or are ready to be recycled.
*/
- ResultStatus flush();
+ BufferPoolStatus flush();
/**
* Allocates a buffer using the specified parameters. Recycles a buffer if
@@ -61,7 +50,7 @@
* NO_MEMORY when there is no memory.
* CRITICAL_ERROR otherwise.
*/
- ResultStatus allocate(const std::vector<uint8_t> ¶ms,
+ BufferPoolStatus allocate(const std::vector<uint8_t> ¶ms,
BufferId *bufferId, const native_handle_t **handle);
/**
@@ -86,7 +75,7 @@
* @param accessor the specified buffer pool.
* @param connectionId Id.
*/
- void initialize(const sp<Accessor> &accessor, ConnectionId connectionId);
+ void initialize(const std::shared_ptr<Accessor> &accessor, ConnectionId connectionId);
enum : uint32_t {
SYNC_BUFFERID = UINT32_MAX,
@@ -94,15 +83,14 @@
private:
bool mInitialized;
- sp<Accessor> mAccessor;
+ std::shared_ptr<Accessor> mAccessor;
ConnectionId mConnectionId;
+
+ bool fetch(
+ uint64_t transactionId,
+ uint32_t bufferId,
+ std::vector<::aidl::android::hardware::media::bufferpool2::IConnection::FetchResult>
+ *result);
};
-} // namespace implementation
-} // namespace V2_0
-} // namespace bufferpool
-} // namespace media
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_CONNECTION_H
+} // namespace aidl::android::hardware::media::bufferpool2::implementation
diff --git a/media/bufferpool/aidl/default/DataHelper.h b/media/bufferpool/aidl/default/DataHelper.h
new file mode 100644
index 0000000..a90b3c7
--- /dev/null
+++ b/media/bufferpool/aidl/default/DataHelper.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/media/bufferpool2/BufferStatusMessage.h>
+#include <bufferpool2/BufferPoolTypes.h>
+
+#include <map>
+#include <set>
+
+namespace aidl::android::hardware::media::bufferpool2::implementation {
+
+// Helper template methods for handling map of set.
+template<class T, class U>
+bool insert(std::map<T, std::set<U>> *mapOfSet, T key, U value) {
+ auto iter = mapOfSet->find(key);
+ if (iter == mapOfSet->end()) {
+ std::set<U> valueSet{value};
+ mapOfSet->insert(std::make_pair(key, valueSet));
+ return true;
+ } else if (iter->second.find(value) == iter->second.end()) {
+ iter->second.insert(value);
+ return true;
+ }
+ return false;
+}
+
+// Helper template methods for handling map of set.
+template<class T, class U>
+bool erase(std::map<T, std::set<U>> *mapOfSet, T key, U value) {
+ bool ret = false;
+ auto iter = mapOfSet->find(key);
+ if (iter != mapOfSet->end()) {
+ if (iter->second.erase(value) > 0) {
+ ret = true;
+ }
+ if (iter->second.size() == 0) {
+ mapOfSet->erase(iter);
+ }
+ }
+ return ret;
+}
+
+// Helper template methods for handling map of set.
+template<class T, class U>
+bool contains(std::map<T, std::set<U>> *mapOfSet, T key, U value) {
+ auto iter = mapOfSet->find(key);
+ if (iter != mapOfSet->end()) {
+ auto setIter = iter->second.find(value);
+ return setIter != iter->second.end();
+ }
+ return false;
+}
+
+// Buffer data structure for internal BufferPool use.(storage/fetching)
+struct InternalBuffer {
+ BufferId mId;
+ size_t mOwnerCount;
+ size_t mTransactionCount;
+ const std::shared_ptr<BufferPoolAllocation> mAllocation;
+ const size_t mAllocSize;
+ const std::vector<uint8_t> mConfig;
+ bool mInvalidated;
+
+ InternalBuffer(
+ BufferId id,
+ const std::shared_ptr<BufferPoolAllocation> &alloc,
+ const size_t allocSize,
+ const std::vector<uint8_t> &allocConfig)
+ : mId(id), mOwnerCount(0), mTransactionCount(0),
+ mAllocation(alloc), mAllocSize(allocSize), mConfig(allocConfig),
+ mInvalidated(false) {}
+
+ const native_handle_t *handle() {
+ return mAllocation->handle();
+ }
+
+ void invalidate() {
+ mInvalidated = true;
+ }
+};
+
+// Buffer transacion status/message data structure for internal BufferPool use.
+struct TransactionStatus {
+ TransactionId mId;
+ BufferId mBufferId;
+ ConnectionId mSender;
+ ConnectionId mReceiver;
+ BufferStatus mStatus;
+ int64_t mTimestampMs;
+ bool mSenderValidated;
+
+ TransactionStatus(const BufferStatusMessage &message, int64_t timestampMs) {
+ mId = message.transactionId;
+ mBufferId = message.bufferId;
+ mStatus = message.status;
+ mTimestampMs = timestampMs;
+ if (mStatus == BufferStatus::TRANSFER_TO) {
+ mSender = message.connectionId;
+ mReceiver = message.targetConnectionId;
+ mSenderValidated = true;
+ } else {
+ mSender = -1LL;
+ mReceiver = message.connectionId;
+ mSenderValidated = false;
+ }
+ }
+};
+
+} // namespace aidl::android::hardware::media::bufferpool2::implementation
diff --git a/media/bufferpool/aidl/default/Observer.cpp b/media/bufferpool/aidl/default/Observer.cpp
index 5b23160..a22e825 100644
--- a/media/bufferpool/aidl/default/Observer.cpp
+++ b/media/bufferpool/aidl/default/Observer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,13 +15,9 @@
*/
#include "Observer.h"
+#include "BufferPoolClient.h"
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
-namespace V2_0 {
-namespace implementation {
+namespace aidl::android::hardware::media::bufferpool2::implementation {
Observer::Observer() {
}
@@ -29,20 +25,19 @@
Observer::~Observer() {
}
-// Methods from ::android::hardware::media::bufferpool::V2_0::IObserver follow.
-Return<void> Observer::onMessage(int64_t connectionId, uint32_t msgId) {
+::ndk::ScopedAStatus Observer::onMessage(int64_t in_connectionId, int32_t in_msgId) {
std::unique_lock<std::mutex> lock(mLock);
- auto it = mClients.find(connectionId);
+ auto it = mClients.find(in_connectionId);
if (it != mClients.end()) {
const std::shared_ptr<BufferPoolClient> client = it->second.lock();
if (!client) {
mClients.erase(it);
} else {
lock.unlock();
- client->receiveInvalidation(msgId);
+ client->receiveInvalidation(in_msgId);
}
}
- return Void();
+ return ::ndk::ScopedAStatus::ok();
}
void Observer::addClient(ConnectionId connectionId,
@@ -65,9 +60,4 @@
}
-} // namespace implementation
-} // namespace V2_0
-} // namespace bufferpool
-} // namespace media
-} // namespace hardware
-} // namespace android
+} // namespace aidl::android::hardware::media::bufferpool2::implementation
diff --git a/media/bufferpool/aidl/default/Observer.h b/media/bufferpool/aidl/default/Observer.h
index 42bd7c1..febb21b 100644
--- a/media/bufferpool/aidl/default/Observer.h
+++ b/media/bufferpool/aidl/default/Observer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,32 +14,20 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_OBSERVER_H
-#define ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_OBSERVER_H
+#pragma once
-#include <android/hardware/media/bufferpool/2.0/IObserver.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-#include "BufferPoolClient.h"
+#include <map>
+#include <memory>
+#include <mutex>
+#include <aidl/android/hardware/media/bufferpool2/BnObserver.h>
+#include <bufferpool2/BufferPoolTypes.h>
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
-namespace V2_0 {
-namespace implementation {
+namespace aidl::android::hardware::media::bufferpool2::implementation {
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
+class BufferPoolClient;
-struct Observer : public IObserver {
- // Methods from ::android::hardware::media::bufferpool::V2_0::IObserver follow.
- Return<void> onMessage(int64_t connectionId, uint32_t msgId) override;
+struct Observer : public BnObserver {
+ ::ndk::ScopedAStatus onMessage(int64_t in_connectionId, int32_t in_msgId) override;
~Observer();
@@ -51,17 +39,11 @@
private:
Observer();
- friend struct ClientManager;
+ friend class ::ndk::SharedRefBase;
std::mutex mLock;
std::map<ConnectionId, const std::weak_ptr<BufferPoolClient>> mClients;
};
-} // namespace implementation
-} // namespace V2_0
-} // namespace bufferpool
-} // namespace media
-} // namespace hardware
-} // namespace android
+} // namespace aidl::android::hardware::media::bufferpool2::implementation
-#endif // ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_OBSERVER_H
diff --git a/media/bufferpool/aidl/default/include/bufferpool/BufferPoolTypes.h b/media/bufferpool/aidl/default/include/bufferpool/BufferPoolTypes.h
deleted file mode 100644
index 7c906cb..0000000
--- a/media/bufferpool/aidl/default/include/bufferpool/BufferPoolTypes.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_BUFFERPOOLTYPES_H
-#define ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_BUFFERPOOLTYPES_H
-
-#include <android/hardware/media/bufferpool/2.0/types.h>
-#include <cutils/native_handle.h>
-#include <fmq/MessageQueue.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
-
-struct BufferPoolData {
- // For local use, to specify a bufferpool (client connection) for buffers.
- // Return value from connect#IAccessor(android.hardware.media.bufferpool@2.0).
- int64_t mConnectionId;
- // BufferId
- uint32_t mId;
-
- BufferPoolData() : mConnectionId(0), mId(0) {}
-
- BufferPoolData(
- int64_t connectionId, uint32_t id)
- : mConnectionId(connectionId), mId(id) {}
-
- ~BufferPoolData() {}
-};
-
-namespace V2_0 {
-namespace implementation {
-
-using ::android::hardware::kSynchronizedReadWrite;
-using ::android::hardware::kUnsynchronizedWrite;
-
-typedef uint32_t BufferId;
-typedef uint64_t TransactionId;
-typedef int64_t ConnectionId;
-
-enum : ConnectionId {
- INVALID_CONNECTIONID = 0,
-};
-
-typedef android::hardware::MessageQueue<BufferStatusMessage, kSynchronizedReadWrite> BufferStatusQueue;
-typedef BufferStatusQueue::Descriptor StatusDescriptor;
-
-typedef android::hardware::MessageQueue<BufferInvalidationMessage, kUnsynchronizedWrite>
- BufferInvalidationQueue;
-typedef BufferInvalidationQueue::Descriptor InvalidationDescriptor;
-
-/**
- * Allocation wrapper class for buffer pool.
- */
-struct BufferPoolAllocation {
- const native_handle_t *mHandle;
-
- const native_handle_t *handle() {
- return mHandle;
- }
-
- BufferPoolAllocation(const native_handle_t *handle) : mHandle(handle) {}
-
- ~BufferPoolAllocation() {};
-};
-
-/**
- * Allocator wrapper class for buffer pool.
- */
-class BufferPoolAllocator {
-public:
-
- /**
- * Allocate an allocation(buffer) for buffer pool.
- *
- * @param params allocation parameters
- * @param alloc created allocation
- * @param allocSize size of created allocation
- *
- * @return OK when an allocation is created successfully.
- */
- virtual ResultStatus allocate(
- const std::vector<uint8_t> ¶ms,
- std::shared_ptr<BufferPoolAllocation> *alloc,
- size_t *allocSize) = 0;
-
- /**
- * Returns whether allocation parameters of an old allocation are
- * compatible with new allocation parameters.
- */
- virtual bool compatible(const std::vector<uint8_t> &newParams,
- const std::vector<uint8_t> &oldParams) = 0;
-
-protected:
- BufferPoolAllocator() = default;
-
- virtual ~BufferPoolAllocator() = default;
-};
-
-} // namespace implementation
-} // namespace V2_0
-} // namespace bufferpool
-} // namespace media
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_BUFFERPOOLTYPES_H
diff --git a/media/bufferpool/aidl/default/include/bufferpool2/BufferPoolTypes.h b/media/bufferpool/aidl/default/include/bufferpool2/BufferPoolTypes.h
new file mode 100644
index 0000000..b833362
--- /dev/null
+++ b/media/bufferpool/aidl/default/include/bufferpool2/BufferPoolTypes.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cutils/native_handle.h>
+#include <fmq/AidlMessageQueue.h>
+#include <aidl/android/hardware/media/bufferpool2/BufferStatusMessage.h>
+#include <aidl/android/hardware/media/bufferpool2/BufferInvalidationMessage.h>
+#include <aidl/android/hardware/media/bufferpool2/ResultStatus.h>
+
+namespace aidl::android::hardware::media::bufferpool2 {
+
+struct BufferPoolData {
+ // For local use, to specify a bufferpool (client connection) for buffers.
+ // Retrieved from returned info of IAccessor#connect(android.hardware.media.bufferpool@2.0).
+ int64_t mConnectionId;
+ // BufferId
+ uint32_t mId;
+
+ BufferPoolData() : mConnectionId(0), mId(0) {}
+
+ BufferPoolData(
+ int64_t connectionId, uint32_t id)
+ : mConnectionId(connectionId), mId(id) {}
+
+ ~BufferPoolData() {}
+};
+
+namespace implementation {
+
+using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using aidl::android::hardware::common::fmq::UnsynchronizedWrite;
+
+using aidl::android::hardware::media::bufferpool2::BufferStatusMessage;
+using aidl::android::hardware::media::bufferpool2::BufferInvalidationMessage;
+
+typedef uint32_t BufferId;
+typedef uint64_t TransactionId;
+typedef int64_t ConnectionId;
+typedef int32_t BufferPoolStatus;
+
+// AIDL hal description language does not support unsigned.
+int32_t static inline ToAidl(BufferId id) {return static_cast<int32_t>(id);}
+int64_t static inline ToAidl(TransactionId id) {return static_cast<int64_t>(id);}
+
+BufferId static inline FromAidl(int32_t id) {return static_cast<BufferId>(id);}
+TransactionId static inline FromAidl(int64_t id) {return static_cast<TransactionId>(id);}
+
+enum : ConnectionId {
+ INVALID_CONNECTIONID = 0,
+};
+
+typedef ::android::AidlMessageQueue<BufferStatusMessage, SynchronizedReadWrite> BufferStatusQueue;
+typedef aidl::android::hardware::common::fmq::MQDescriptor<BufferStatusMessage, SynchronizedReadWrite>
+ StatusDescriptor;
+
+typedef ::android::AidlMessageQueue<BufferInvalidationMessage, UnsynchronizedWrite>
+ BufferInvalidationQueue;
+typedef aidl::android::hardware::common::fmq::MQDescriptor<BufferInvalidationMessage, UnsynchronizedWrite>
+ InvalidationDescriptor;
+
+/**
+ * Allocation wrapper class for buffer pool.
+ */
+struct BufferPoolAllocation {
+ const native_handle_t *mHandle;
+
+ const native_handle_t *handle() {
+ return mHandle;
+ }
+
+ BufferPoolAllocation(const native_handle_t *handle) : mHandle(handle) {}
+
+ ~BufferPoolAllocation() {};
+};
+
+/**
+ * Allocator wrapper class for buffer pool.
+ */
+class BufferPoolAllocator {
+public:
+
+ /**
+ * Allocate an allocation(buffer) for buffer pool.
+ *
+ * @param params allocation parameters
+ * @param alloc created allocation
+ * @param allocSize size of created allocation
+ *
+ * @return OK when an allocation is created successfully.
+ */
+ virtual BufferPoolStatus allocate(
+ const std::vector<uint8_t> ¶ms,
+ std::shared_ptr<BufferPoolAllocation> *alloc,
+ size_t *allocSize) = 0;
+
+ /**
+ * Returns whether allocation parameters of an old allocation are
+ * compatible with new allocation parameters.
+ */
+ virtual bool compatible(const std::vector<uint8_t> &newParams,
+ const std::vector<uint8_t> &oldParams) = 0;
+
+protected:
+ BufferPoolAllocator() = default;
+
+ virtual ~BufferPoolAllocator() = default;
+};
+
+} // namespace implementation
+} // namespace aidl::android::hareware::media::bufferpool2
+
diff --git a/media/bufferpool/aidl/default/include/bufferpool/ClientManager.h b/media/bufferpool/aidl/default/include/bufferpool2/ClientManager.h
similarity index 71%
rename from media/bufferpool/aidl/default/include/bufferpool/ClientManager.h
rename to media/bufferpool/aidl/default/include/bufferpool2/ClientManager.h
index 24b61f4..bff75ba 100644
--- a/media/bufferpool/aidl/default/include/bufferpool/ClientManager.h
+++ b/media/bufferpool/aidl/default/include/bufferpool2/ClientManager.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,38 +14,28 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_CLIENTMANAGER_H
-#define ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_CLIENTMANAGER_H
+#pragma once
-#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
+#include <aidl/android/hardware/media/bufferpool2/IAccessor.h>
+#include <aidl/android/hardware/media/bufferpool2/BnClientManager.h>
#include <memory>
#include "BufferPoolTypes.h"
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
-namespace V2_0 {
-namespace implementation {
+namespace aidl::android::hardware::media::bufferpool2::implementation {
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::media::bufferpool::V2_0::IAccessor;
-using ::android::hardware::media::bufferpool::V2_0::ResultStatus;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
+using aidl::android::hardware::media::bufferpool2::BnClientManager;
+using aidl::android::hardware::media::bufferpool2::IClientManager;
+using aidl::android::hardware::media::bufferpool2::IAccessor;
-struct ClientManager : public IClientManager {
- // Methods from ::android::hardware::media::bufferpool::V2_0::IClientManager follow.
- Return<void> registerSender(const sp<::android::hardware::media::bufferpool::V2_0::IAccessor>& bufferPool, registerSender_cb _hidl_cb) override;
+struct ClientManager : public BnClientManager {
+ // Methods from ::aidl::android::hardware::media::bufferpool2::IClientManager follow.
+ ::ndk::ScopedAStatus registerSender(
+ const std::shared_ptr<IAccessor>& in_bufferPool,
+ ::aidl::android::hardware::media::bufferpool2::IClientManager::Registration* _aidl_return)
+ override;
/** Gets an instance. */
- static sp<ClientManager> getInstance();
+ static std::shared_ptr<ClientManager> getInstance();
/**
* Creates a local connection with a newly created buffer pool.
@@ -56,10 +46,10 @@
*
* @return OK when a buffer pool and a local connection is successfully
* created.
- * NO_MEMORY when there is no memory.
+ * ResultStatus::NO_MEMORY when there is no memory.
* CRITICAL_ERROR otherwise.
*/
- ResultStatus create(const std::shared_ptr<BufferPoolAllocator> &allocator,
+ BufferPoolStatus create(const std::shared_ptr<BufferPoolAllocator> &allocator,
ConnectionId *pConnectionId);
/**
@@ -69,16 +59,17 @@
* @param senderId A local connection which will send buffers to.
* @param receiverId Id of the created receiving connection on the receiver
* process.
+ * @param isNew @true when the receiving connection is newly created.
*
* @return OK when the receiving connection is successfully created on the
* receiver process.
* NOT_FOUND when the sender connection was not found.
- * ALREADY_EXISTS the receiving connection is already made.
* CRITICAL_ERROR otherwise.
*/
- ResultStatus registerSender(const sp<IClientManager> &receiver,
+ BufferPoolStatus registerSender(const std::shared_ptr<IClientManager> &receiver,
ConnectionId senderId,
- ConnectionId *receiverId);
+ ConnectionId *receiverId,
+ bool *isNew);
/**
* Closes the specified connection.
@@ -89,7 +80,7 @@
* NOT_FOUND when the specified connection was not found.
* CRITICAL_ERROR otherwise.
*/
- ResultStatus close(ConnectionId connectionId);
+ BufferPoolStatus close(ConnectionId connectionId);
/**
* Evicts cached allocations. If it's local connection, release the
@@ -101,7 +92,7 @@
* NOT_FOUND when the specified connection was not found.
* CRITICAL_ERROR otherwise.
*/
- ResultStatus flush(ConnectionId connectionId);
+ BufferPoolStatus flush(ConnectionId connectionId);
/**
* Allocates a buffer from the specified connection. The output parameter
@@ -119,7 +110,7 @@
* NO_MEMORY when there is no memory.
* CRITICAL_ERROR otherwise.
*/
- ResultStatus allocate(ConnectionId connectionId,
+ BufferPoolStatus allocate(ConnectionId connectionId,
const std::vector<uint8_t> ¶ms,
native_handle_t **handle,
std::shared_ptr<BufferPoolData> *buffer);
@@ -132,7 +123,7 @@
* @param connectionId The id of the receiving connection.
* @param transactionId The id for the transaction.
* @param bufferId The id for the buffer.
- * @param timestampUs The timestamp of the buffer is being sent.
+ * @param timestampMs The timestamp of the buffer is being sent.
* @param handle The native handle to the allocated buffer. handle
* should be cloned before use.
* @param buffer The received buffer.
@@ -142,10 +133,10 @@
* NO_MEMORY when there is no memory.
* CRITICAL_ERROR otherwise.
*/
- ResultStatus receive(ConnectionId connectionId,
+ BufferPoolStatus receive(ConnectionId connectionId,
TransactionId transactionId,
BufferId bufferId,
- int64_t timestampUs,
+ int64_t timestampMs,
native_handle_t **handle,
std::shared_ptr<BufferPoolData> *buffer);
@@ -156,17 +147,17 @@
* @param receiverId The id of the receiving connection.
* @param buffer to transfer
* @param transactionId Id of the transfer transaction.
- * @param timestampUs The timestamp of the buffer transaction is being
+ * @param timestampMs The timestamp of the buffer transaction is being
* posted.
*
* @return OK when a buffer transaction was posted successfully.
* NOT_FOUND when the sending connection was not found.
* CRITICAL_ERROR otherwise.
*/
- ResultStatus postSend(ConnectionId receiverId,
+ BufferPoolStatus postSend(ConnectionId receiverId,
const std::shared_ptr<BufferPoolData> &buffer,
TransactionId *transactionId,
- int64_t *timestampUs);
+ int64_t *timestampMs);
/**
* Time out inactive lingering connections and close.
@@ -176,20 +167,16 @@
/** Destructs the manager of buffer pool clients. */
~ClientManager();
private:
- static sp<ClientManager> sInstance;
+ static std::shared_ptr<ClientManager> sInstance;
static std::mutex sInstanceLock;
class Impl;
const std::unique_ptr<Impl> mImpl;
+ friend class ::ndk::SharedRefBase;
+
ClientManager();
};
-} // namespace implementation
-} // namespace V2_0
-} // namespace bufferpool
-} // namespace media
-} // namespace hardware
-} // namespace android
+} // namespace aidl::android::hardware::media::bufferpool2::implementation
-#endif // ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_CLIENTMANAGER_H
diff --git a/media/bufferpool/aidl/default/tests/Android.bp b/media/bufferpool/aidl/default/tests/Android.bp
new file mode 100644
index 0000000..549af57
--- /dev/null
+++ b/media/bufferpool/aidl/default/tests/Android.bp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsVndkAidlBufferpool2V1_0TargetSingleTest",
+ test_suites: ["device-tests"],
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "allocator.cpp",
+ "single.cpp",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "libcutils",
+ "libfmq",
+ "liblog",
+ "libutils",
+ "android.hardware.media.bufferpool2-V1-ndk",
+ ],
+ static_libs: [
+ "libaidlcommonsupport",
+ "libstagefright_aidl_bufferpool2"
+ ],
+ compile_multilib: "both",
+}
+
+cc_test {
+ name: "VtsVndkAidlBufferpool2V1_0TargetMultiTest",
+ test_suites: ["device-tests"],
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "allocator.cpp",
+ "multi.cpp",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "libcutils",
+ "libfmq",
+ "liblog",
+ "libutils",
+ "android.hardware.media.bufferpool2-V1-ndk",
+ ],
+ static_libs: [
+ "libaidlcommonsupport",
+ "libstagefright_aidl_bufferpool2"
+ ],
+ compile_multilib: "both",
+}
+
+cc_test {
+ name: "VtsVndkAidlBufferpool2V1_0TargetCondTest",
+ test_suites: ["device-tests"],
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "allocator.cpp",
+ "cond.cpp",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "libcutils",
+ "libfmq",
+ "liblog",
+ "libutils",
+ "android.hardware.media.bufferpool2-V1-ndk",
+ ],
+ static_libs: [
+ "libaidlcommonsupport",
+ "libstagefright_aidl_bufferpool2"
+ ],
+ compile_multilib: "both",
+}
diff --git a/media/bufferpool/aidl/default/tests/BufferpoolUnitTest.cpp b/media/bufferpool/aidl/default/tests/BufferpoolUnitTest.cpp
deleted file mode 100644
index b448405..0000000
--- a/media/bufferpool/aidl/default/tests/BufferpoolUnitTest.cpp
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "BufferpoolUnitTest"
-#include <utils/Log.h>
-
-#include <binder/ProcessState.h>
-#include <bufferpool/ClientManager.h>
-#include <gtest/gtest.h>
-#include <hidl/LegacySupport.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unordered_set>
-#include <vector>
-#include "allocator.h"
-
-using android::hardware::configureRpcThreadpool;
-using android::hardware::media::bufferpool::BufferPoolData;
-using android::hardware::media::bufferpool::V2_0::IClientManager;
-using android::hardware::media::bufferpool::V2_0::ResultStatus;
-using android::hardware::media::bufferpool::V2_0::implementation::BufferId;
-using android::hardware::media::bufferpool::V2_0::implementation::ClientManager;
-using android::hardware::media::bufferpool::V2_0::implementation::ConnectionId;
-using android::hardware::media::bufferpool::V2_0::implementation::TransactionId;
-
-using namespace android;
-
-// communication message types between processes.
-enum PipeCommand : int32_t {
- INIT,
- TRANSFER,
- STOP,
-
- INIT_OK,
- INIT_ERROR,
- TRANSFER_OK,
- TRANSFER_ERROR,
- STOP_OK,
- STOP_ERROR,
-};
-
-// communication message between processes.
-union PipeMessage {
- struct {
- int32_t command;
- int32_t memsetValue;
- BufferId bufferId;
- ConnectionId connectionId;
- TransactionId transactionId;
- int64_t timestampUs;
- } data;
- char array[0];
-};
-
-static int32_t kNumIterationCount = 10;
-
-class BufferpoolTest {
- public:
- BufferpoolTest() : mConnectionValid(false), mManager(nullptr), mAllocator(nullptr) {
- mConnectionId = -1;
- mReceiverId = -1;
- }
-
- ~BufferpoolTest() {
- if (mConnectionValid) {
- mManager->close(mConnectionId);
- }
- }
-
- protected:
- bool mConnectionValid;
- ConnectionId mConnectionId;
- ConnectionId mReceiverId;
-
- android::sp<ClientManager> mManager;
- std::shared_ptr<BufferPoolAllocator> mAllocator;
-
- void setupBufferpoolManager();
-};
-
-void BufferpoolTest::setupBufferpoolManager() {
- // retrieving per process bufferpool object sp<ClientManager>
- mManager = ClientManager::getInstance();
- ASSERT_NE(mManager, nullptr) << "unable to get ClientManager\n";
-
- mAllocator = std::make_shared<TestBufferPoolAllocator>();
- ASSERT_NE(mAllocator, nullptr) << "unable to create TestBufferPoolAllocator\n";
-
- // set-up local bufferpool connection for sender
- ResultStatus status = mManager->create(mAllocator, &mConnectionId);
- ASSERT_EQ(status, ResultStatus::OK)
- << "unable to set-up local bufferpool connection for sender\n";
- mConnectionValid = true;
-}
-
-class BufferpoolUnitTest : public BufferpoolTest, public ::testing::Test {
- public:
- virtual void SetUp() override { setupBufferpoolManager(); }
-
- virtual void TearDown() override {}
-};
-
-class BufferpoolFunctionalityTest : public BufferpoolTest, public ::testing::Test {
- public:
- virtual void SetUp() override {
- mReceiverPid = -1;
-
- ASSERT_TRUE(pipe(mCommandPipeFds) == 0) << "pipe connection failed for commandPipe\n";
- ASSERT_TRUE(pipe(mResultPipeFds) == 0) << "pipe connection failed for resultPipe\n";
-
- mReceiverPid = fork();
- ASSERT_TRUE(mReceiverPid >= 0) << "fork failed\n";
-
- if (mReceiverPid == 0) {
- doReceiver();
- // In order to ignore gtest behaviour, wait for being killed from tearDown
- pause();
- }
- setupBufferpoolManager();
- }
-
- virtual void TearDown() override {
- if (mReceiverPid > 0) {
- kill(mReceiverPid, SIGKILL);
- int wstatus;
- wait(&wstatus);
- }
- }
-
- protected:
- pid_t mReceiverPid;
- int mCommandPipeFds[2];
- int mResultPipeFds[2];
-
- bool sendMessage(int* pipes, const PipeMessage& message) {
- int ret = write(pipes[1], message.array, sizeof(PipeMessage));
- return ret == sizeof(PipeMessage);
- }
-
- bool receiveMessage(int* pipes, PipeMessage* message) {
- int ret = read(pipes[0], message->array, sizeof(PipeMessage));
- return ret == sizeof(PipeMessage);
- }
-
- void doReceiver();
-};
-
-void BufferpoolFunctionalityTest::doReceiver() {
- // Configures the threadpool used for handling incoming RPC calls in this process.
- configureRpcThreadpool(1 /*threads*/, false /*willJoin*/);
- bool receiverRunning = true;
- while (receiverRunning) {
- PipeMessage message;
- receiveMessage(mCommandPipeFds, &message);
- ResultStatus err = ResultStatus::OK;
- switch (message.data.command) {
- case PipeCommand::INIT: {
- // receiver manager creation
- mManager = ClientManager::getInstance();
- if (!mManager) {
- message.data.command = PipeCommand::INIT_ERROR;
- sendMessage(mResultPipeFds, message);
- return;
- }
-
- android::status_t status = mManager->registerAsService();
- if (status != android::OK) {
- message.data.command = PipeCommand::INIT_ERROR;
- sendMessage(mResultPipeFds, message);
- return;
- }
- message.data.command = PipeCommand::INIT_OK;
- sendMessage(mResultPipeFds, message);
- break;
- }
- case PipeCommand::TRANSFER: {
- native_handle_t* receiveHandle = nullptr;
- std::shared_ptr<BufferPoolData> receiveBuffer;
- err = mManager->receive(message.data.connectionId, message.data.transactionId,
- message.data.bufferId, message.data.timestampUs,
- &receiveHandle, &receiveBuffer);
- if (err != ResultStatus::OK) {
- message.data.command = PipeCommand::TRANSFER_ERROR;
- sendMessage(mResultPipeFds, message);
- return;
- }
- if (!TestBufferPoolAllocator::Verify(receiveHandle, message.data.memsetValue)) {
- message.data.command = PipeCommand::TRANSFER_ERROR;
- sendMessage(mResultPipeFds, message);
- return;
- }
- if (receiveHandle) {
- native_handle_close(receiveHandle);
- native_handle_delete(receiveHandle);
- }
- receiveHandle = nullptr;
- receiveBuffer.reset();
- message.data.command = PipeCommand::TRANSFER_OK;
- sendMessage(mResultPipeFds, message);
- break;
- }
- case PipeCommand::STOP: {
- err = mManager->close(message.data.connectionId);
- if (err != ResultStatus::OK) {
- message.data.command = PipeCommand::STOP_ERROR;
- sendMessage(mResultPipeFds, message);
- return;
- }
- message.data.command = PipeCommand::STOP_OK;
- sendMessage(mResultPipeFds, message);
- receiverRunning = false;
- break;
- }
- default:
- ALOGE("unknown command. try again");
- break;
- }
- }
-}
-
-// Buffer allocation test.
-// Check whether each buffer allocation is done successfully with unique buffer id.
-TEST_F(BufferpoolUnitTest, AllocateBuffer) {
- std::vector<uint8_t> vecParams;
- getTestAllocatorParams(&vecParams);
-
- std::vector<std::shared_ptr<BufferPoolData>> buffers{};
- std::vector<native_handle_t*> allocHandle{};
- ResultStatus status;
- for (int i = 0; i < kNumIterationCount; ++i) {
- native_handle_t* handle = nullptr;
- std::shared_ptr<BufferPoolData> buffer{};
- status = mManager->allocate(mConnectionId, vecParams, &handle, &buffer);
- ASSERT_EQ(status, ResultStatus::OK) << "allocate failed for " << i << "iteration";
-
- buffers.push_back(std::move(buffer));
- if (handle) {
- allocHandle.push_back(std::move(handle));
- }
- }
-
- for (int i = 0; i < kNumIterationCount; ++i) {
- for (int j = i + 1; j < kNumIterationCount; ++j) {
- ASSERT_TRUE(buffers[i]->mId != buffers[j]->mId) << "allocated buffers are not unique";
- }
- }
- // delete the buffer handles
- for (auto handle : allocHandle) {
- native_handle_close(handle);
- native_handle_delete(handle);
- }
- // clear the vectors
- buffers.clear();
- allocHandle.clear();
-}
-
-// Buffer recycle test.
-// Check whether de-allocated buffers are recycled.
-TEST_F(BufferpoolUnitTest, RecycleBuffer) {
- std::vector<uint8_t> vecParams;
- getTestAllocatorParams(&vecParams);
-
- ResultStatus status;
- std::vector<BufferId> bid{};
- std::vector<native_handle_t*> allocHandle{};
- for (int i = 0; i < kNumIterationCount; ++i) {
- native_handle_t* handle = nullptr;
- std::shared_ptr<BufferPoolData> buffer;
- status = mManager->allocate(mConnectionId, vecParams, &handle, &buffer);
- ASSERT_EQ(status, ResultStatus::OK) << "allocate failed for " << i << "iteration";
-
- bid.push_back(buffer->mId);
- if (handle) {
- allocHandle.push_back(std::move(handle));
- }
- buffer.reset();
- }
-
- std::unordered_set<BufferId> set(bid.begin(), bid.end());
- ASSERT_EQ(set.size(), 1) << "buffers are not recycled properly";
-
- // delete the buffer handles
- for (auto handle : allocHandle) {
- native_handle_close(handle);
- native_handle_delete(handle);
- }
- allocHandle.clear();
-}
-
-// Validate cache evict and invalidate APIs.
-TEST_F(BufferpoolUnitTest, FlushTest) {
- std::vector<uint8_t> vecParams;
- getTestAllocatorParams(&vecParams);
-
- ResultStatus status = mManager->registerSender(mManager, mConnectionId, &mReceiverId);
- ASSERT_TRUE(status == ResultStatus::ALREADY_EXISTS && mReceiverId == mConnectionId);
-
- // testing empty flush
- status = mManager->flush(mConnectionId);
- ASSERT_EQ(status, ResultStatus::OK) << "failed to flush connection : " << mConnectionId;
-
- std::vector<std::shared_ptr<BufferPoolData>> senderBuffer{};
- std::vector<native_handle_t*> allocHandle{};
- std::vector<TransactionId> tid{};
- std::vector<int64_t> timestampUs{};
-
- std::map<TransactionId, BufferId> bufferMap{};
-
- for (int i = 0; i < kNumIterationCount; i++) {
- int64_t postUs;
- TransactionId transactionId;
- native_handle_t* handle = nullptr;
- std::shared_ptr<BufferPoolData> buffer{};
- status = mManager->allocate(mConnectionId, vecParams, &handle, &buffer);
- ASSERT_EQ(status, ResultStatus::OK) << "allocate failed for " << i << " iteration";
-
- ASSERT_TRUE(TestBufferPoolAllocator::Fill(handle, i));
-
- status = mManager->postSend(mReceiverId, buffer, &transactionId, &postUs);
- ASSERT_EQ(status, ResultStatus::OK) << "unable to post send transaction on bufferpool";
-
- timestampUs.push_back(postUs);
- tid.push_back(transactionId);
- bufferMap.insert({transactionId, buffer->mId});
-
- senderBuffer.push_back(std::move(buffer));
- if (handle) {
- allocHandle.push_back(std::move(handle));
- }
- buffer.reset();
- }
-
- status = mManager->flush(mConnectionId);
- ASSERT_EQ(status, ResultStatus::OK) << "failed to flush connection : " << mConnectionId;
-
- std::shared_ptr<BufferPoolData> receiverBuffer{};
- native_handle_t* recvHandle = nullptr;
- for (int i = 0; i < kNumIterationCount; i++) {
- status = mManager->receive(mReceiverId, tid[i], senderBuffer[i]->mId, timestampUs[i],
- &recvHandle, &receiverBuffer);
- ASSERT_EQ(status, ResultStatus::OK) << "receive failed for buffer " << senderBuffer[i]->mId;
-
- // find the buffer id from transaction id
- auto findIt = bufferMap.find(tid[i]);
- ASSERT_NE(findIt, bufferMap.end()) << "inconsistent buffer mapping";
-
- // buffer id received must be same as the buffer id sent
- ASSERT_EQ(findIt->second, receiverBuffer->mId) << "invalid buffer received";
-
- ASSERT_TRUE(TestBufferPoolAllocator::Verify(recvHandle, i))
- << "Message received not same as that sent";
-
- bufferMap.erase(findIt);
- if (recvHandle) {
- native_handle_close(recvHandle);
- native_handle_delete(recvHandle);
- }
- recvHandle = nullptr;
- receiverBuffer.reset();
- }
-
- ASSERT_EQ(bufferMap.size(), 0) << "buffers received is less than the number of buffers sent";
-
- for (auto handle : allocHandle) {
- native_handle_close(handle);
- native_handle_delete(handle);
- }
- allocHandle.clear();
- senderBuffer.clear();
- timestampUs.clear();
-}
-
-// Buffer transfer test between processes.
-TEST_F(BufferpoolFunctionalityTest, TransferBuffer) {
- // initialize the receiver
- PipeMessage message;
- message.data.command = PipeCommand::INIT;
- sendMessage(mCommandPipeFds, message);
- ASSERT_TRUE(receiveMessage(mResultPipeFds, &message)) << "receiveMessage failed\n";
- ASSERT_EQ(message.data.command, PipeCommand::INIT_OK) << "receiver init failed";
-
- android::sp<IClientManager> receiver = IClientManager::getService();
- ASSERT_NE(receiver, nullptr) << "getService failed for receiver\n";
-
- ConnectionId receiverId;
- ResultStatus status = mManager->registerSender(receiver, mConnectionId, &receiverId);
- ASSERT_EQ(status, ResultStatus::OK)
- << "registerSender failed for connection id " << mConnectionId << "\n";
-
- std::vector<uint8_t> vecParams;
- getTestAllocatorParams(&vecParams);
-
- for (int i = 0; i < kNumIterationCount; ++i) {
- native_handle_t* handle = nullptr;
- std::shared_ptr<BufferPoolData> buffer;
- status = mManager->allocate(mConnectionId, vecParams, &handle, &buffer);
- ASSERT_EQ(status, ResultStatus::OK) << "allocate failed for " << i << "iteration";
-
- ASSERT_TRUE(TestBufferPoolAllocator::Fill(handle, i))
- << "Fill fail for buffer handle " << handle << "\n";
-
- // send the buffer to the receiver
- int64_t postUs;
- TransactionId transactionId;
- status = mManager->postSend(receiverId, buffer, &transactionId, &postUs);
- ASSERT_EQ(status, ResultStatus::OK)
- << "postSend failed for receiver " << receiverId << "\n";
-
- // PipeMessage message;
- message.data.command = PipeCommand::TRANSFER;
- message.data.memsetValue = i;
- message.data.bufferId = buffer->mId;
- message.data.connectionId = receiverId;
- message.data.transactionId = transactionId;
- message.data.timestampUs = postUs;
- sendMessage(mCommandPipeFds, message);
- // delete buffer handle
- if (handle) {
- native_handle_close(handle);
- native_handle_delete(handle);
- }
- ASSERT_TRUE(receiveMessage(mResultPipeFds, &message)) << "receiveMessage failed\n";
- ASSERT_EQ(message.data.command, PipeCommand::TRANSFER_OK)
- << "received error during buffer transfer\n";
- }
- message.data.command = PipeCommand::STOP;
- sendMessage(mCommandPipeFds, message);
- ASSERT_TRUE(receiveMessage(mResultPipeFds, &message)) << "receiveMessage failed\n";
- ASSERT_EQ(message.data.command, PipeCommand::STOP_OK)
- << "received error during buffer transfer\n";
-}
-
-/* Validate bufferpool for following corner cases:
- 1. invalid connectionID
- 2. invalid receiver
- 3. when sender is not registered
- 4. when connection is closed
-*/
-// TODO: Enable when the issue in b/212196495 is fixed
-TEST_F(BufferpoolFunctionalityTest, DISABLED_ValidityTest) {
- std::vector<uint8_t> vecParams;
- getTestAllocatorParams(&vecParams);
-
- std::shared_ptr<BufferPoolData> senderBuffer;
- native_handle_t* allocHandle = nullptr;
-
- // call allocate() on a random connection id
- ConnectionId randomId = rand();
- ResultStatus status = mManager->allocate(randomId, vecParams, &allocHandle, &senderBuffer);
- EXPECT_TRUE(status == ResultStatus::NOT_FOUND);
-
- // initialize the receiver
- PipeMessage message;
- message.data.command = PipeCommand::INIT;
- sendMessage(mCommandPipeFds, message);
- ASSERT_TRUE(receiveMessage(mResultPipeFds, &message)) << "receiveMessage failed\n";
- ASSERT_EQ(message.data.command, PipeCommand::INIT_OK) << "receiver init failed";
-
- allocHandle = nullptr;
- senderBuffer.reset();
- status = mManager->allocate(mConnectionId, vecParams, &allocHandle, &senderBuffer);
-
- ASSERT_TRUE(TestBufferPoolAllocator::Fill(allocHandle, 0x77));
-
- // send buffers w/o registering sender
- int64_t postUs;
- TransactionId transactionId;
-
- // random receiver
- status = mManager->postSend(randomId, senderBuffer, &transactionId, &postUs);
- ASSERT_NE(status, ResultStatus::OK) << "bufferpool shouldn't allow send on random receiver";
-
- // establish connection
- android::sp<IClientManager> receiver = IClientManager::getService();
- ASSERT_NE(receiver, nullptr) << "getService failed for receiver\n";
-
- ConnectionId receiverId;
- status = mManager->registerSender(receiver, mConnectionId, &receiverId);
- ASSERT_EQ(status, ResultStatus::OK)
- << "registerSender failed for connection id " << mConnectionId << "\n";
-
- allocHandle = nullptr;
- senderBuffer.reset();
- status = mManager->allocate(mConnectionId, vecParams, &allocHandle, &senderBuffer);
- ASSERT_EQ(status, ResultStatus::OK) << "allocate failed for connection " << mConnectionId;
-
- ASSERT_TRUE(TestBufferPoolAllocator::Fill(allocHandle, 0x88));
-
- // send the buffer to the receiver
- status = mManager->postSend(receiverId, senderBuffer, &transactionId, &postUs);
- ASSERT_EQ(status, ResultStatus::OK) << "postSend failed for receiver " << receiverId << "\n";
-
- // PipeMessage message;
- message.data.command = PipeCommand::TRANSFER;
- message.data.memsetValue = 0x88;
- message.data.bufferId = senderBuffer->mId;
- message.data.connectionId = receiverId;
- message.data.transactionId = transactionId;
- message.data.timestampUs = postUs;
- sendMessage(mCommandPipeFds, message);
- ASSERT_TRUE(receiveMessage(mResultPipeFds, &message)) << "receiveMessage failed\n";
- ASSERT_EQ(message.data.command, PipeCommand::TRANSFER_OK)
- << "received error during buffer transfer\n";
-
- if (allocHandle) {
- native_handle_close(allocHandle);
- native_handle_delete(allocHandle);
- }
-
- message.data.command = PipeCommand::STOP;
- sendMessage(mCommandPipeFds, message);
- ASSERT_TRUE(receiveMessage(mResultPipeFds, &message)) << "receiveMessage failed\n";
- ASSERT_EQ(message.data.command, PipeCommand::STOP_OK)
- << "received error during buffer transfer\n";
-
- // try to send msg to closed connection
- status = mManager->postSend(receiverId, senderBuffer, &transactionId, &postUs);
- ASSERT_NE(status, ResultStatus::OK) << "bufferpool shouldn't allow send on closed connection";
-}
-
-int main(int argc, char** argv) {
- android::hardware::details::setTrebleTestingOverride(true);
- ::testing::InitGoogleTest(&argc, argv);
- int status = RUN_ALL_TESTS();
- ALOGV("Test result = %d\n", status);
- return status;
-}
diff --git a/media/bufferpool/aidl/default/tests/allocator.cpp b/media/bufferpool/aidl/default/tests/allocator.cpp
index 25b08ef..16b33a6 100644
--- a/media/bufferpool/aidl/default/tests/allocator.cpp
+++ b/media/bufferpool/aidl/default/tests/allocator.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -139,7 +139,7 @@
}
-ResultStatus TestBufferPoolAllocator::allocate(
+BufferPoolStatus TestBufferPoolAllocator::allocate(
const std::vector<uint8_t> ¶ms,
std::shared_ptr<BufferPoolAllocation> *alloc,
size_t *allocSize) {
diff --git a/media/bufferpool/aidl/default/tests/allocator.h b/media/bufferpool/aidl/default/tests/allocator.h
index 862d1a5..7e7203f 100644
--- a/media/bufferpool/aidl/default/tests/allocator.h
+++ b/media/bufferpool/aidl/default/tests/allocator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,18 @@
* limitations under the License.
*/
-#ifndef VNDK_HIDL_BUFFERPOOL_V2_0_ALLOCATOR_H
-#define VNDK_HIDL_BUFFERPOOL_V2_0_ALLOCATOR_H
+#pragma once
#include <pthread.h>
-#include <bufferpool/BufferPoolTypes.h>
+#include <bufferpool2/BufferPoolTypes.h>
-using android::hardware::media::bufferpool::V2_0::ResultStatus;
-using android::hardware::media::bufferpool::V2_0::implementation::
+using aidl::android::hardware::media::bufferpool2::implementation::
+ BufferPoolStatus;
+using aidl::android::hardware::media::bufferpool2::implementation::
BufferPoolAllocation;
-using android::hardware::media::bufferpool::V2_0::implementation::
+using aidl::android::hardware::media::bufferpool2::implementation::
BufferPoolAllocator;
+using aidl::android::hardware::media::bufferpool2::ResultStatus;
struct IpcMutex {
pthread_mutex_t lock;
@@ -44,7 +45,7 @@
~TestBufferPoolAllocator() override {}
- ResultStatus allocate(const std::vector<uint8_t> ¶ms,
+ BufferPoolStatus allocate(const std::vector<uint8_t> ¶ms,
std::shared_ptr<BufferPoolAllocation> *alloc,
size_t *allocSize) override;
@@ -60,9 +61,7 @@
static bool UnmapMemoryForMutex(void *mem);
};
-// retrieve buffer allocator paramters
+// retrieve buffer allocator parameters
void getTestAllocatorParams(std::vector<uint8_t> *params);
void getIpcMutexParams(std::vector<uint8_t> *params);
-
-#endif // VNDK_HIDL_BUFFERPOOL_V2_0_ALLOCATOR_H
diff --git a/media/bufferpool/aidl/default/tests/cond.cpp b/media/bufferpool/aidl/default/tests/cond.cpp
index 21beea8..6d469ce 100644
--- a/media/bufferpool/aidl/default/tests/cond.cpp
+++ b/media/bufferpool/aidl/default/tests/cond.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,35 +18,36 @@
#include <gtest/gtest.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/binder_stability.h>
#include <android-base/logging.h>
-#include <binder/ProcessState.h>
-#include <bufferpool/ClientManager.h>
+#include <bufferpool2/ClientManager.h>
+
#include <errno.h>
-#include <hidl/HidlSupport.h>
-#include <hidl/HidlTransportSupport.h>
-#include <hidl/LegacySupport.h>
-#include <hidl/Status.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
+
#include <iostream>
#include <memory>
#include <vector>
+
#include "allocator.h"
-using android::hardware::configureRpcThreadpool;
-using android::hardware::hidl_handle;
-using android::hardware::media::bufferpool::V2_0::IClientManager;
-using android::hardware::media::bufferpool::V2_0::ResultStatus;
-using android::hardware::media::bufferpool::V2_0::implementation::BufferId;
-using android::hardware::media::bufferpool::V2_0::implementation::ClientManager;
-using android::hardware::media::bufferpool::V2_0::implementation::ConnectionId;
-using android::hardware::media::bufferpool::V2_0::implementation::TransactionId;
-using android::hardware::media::bufferpool::BufferPoolData;
+using aidl::android::hardware::media::bufferpool2::IClientManager;
+using aidl::android::hardware::media::bufferpool2::ResultStatus;
+using aidl::android::hardware::media::bufferpool2::implementation::BufferId;
+using aidl::android::hardware::media::bufferpool2::implementation::ClientManager;
+using aidl::android::hardware::media::bufferpool2::implementation::ConnectionId;
+using aidl::android::hardware::media::bufferpool2::implementation::TransactionId;
+using aidl::android::hardware::media::bufferpool2::BufferPoolData;
namespace {
+const std::string testInstance = std::string() + ClientManager::descriptor + "/condtest";
+
// communication message types between processes.
enum PipeCommand : int32_t {
INIT_OK = 0,
@@ -74,7 +75,7 @@
class BufferpoolMultiTest : public ::testing::Test {
public:
virtual void SetUp() override {
- ResultStatus status;
+ BufferPoolStatus status;
mReceiverPid = -1;
mConnectionValid = false;
@@ -119,7 +120,7 @@
RecordProperty("description", description);
}
- android::sp<ClientManager> mManager;
+ std::shared_ptr<ClientManager> mManager;
std::shared_ptr<BufferPoolAllocator> mAllocator;
bool mConnectionValid;
ConnectionId mConnectionId;
@@ -138,7 +139,8 @@
}
void doReceiver() {
- configureRpcThreadpool(1, false);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
PipeMessage message;
mManager = ClientManager::getInstance();
if (!mManager) {
@@ -146,7 +148,11 @@
sendMessage(mResultPipeFds, message);
return;
}
- android::status_t status = mManager->registerAsService();
+ auto binder = mManager->asBinder();
+ AIBinder_forceDowngradeToSystemStability(binder.get());
+ binder_status_t status =
+ AServiceManager_addService(binder.get(), testInstance.c_str());
+ CHECK_EQ(status, STATUS_OK);
if (status != android::OK) {
message.data.command = PipeCommand::INIT_ERROR;
sendMessage(mResultPipeFds, message);
@@ -162,7 +168,7 @@
std::shared_ptr<BufferPoolData> rbuffer;
void *mem = nullptr;
IpcMutex *mutex = nullptr;
- ResultStatus status = mManager->receive(
+ BufferPoolStatus status = mManager->receive(
message.data.connectionId, message.data.transactionId,
message.data.bufferId, message.data.timestampUs, &rhandle, &rbuffer);
mManager->close(message.data.connectionId);
@@ -201,16 +207,22 @@
// Buffer transfer test between processes.
TEST_F(BufferpoolMultiTest, TransferBuffer) {
- ResultStatus status;
+ BufferPoolStatus status;
PipeMessage message;
ASSERT_TRUE(receiveMessage(mResultPipeFds, &message));
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
- android::sp<IClientManager> receiver = IClientManager::getService();
+
+ std::shared_ptr<IClientManager> receiver =
+ IClientManager::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(testInstance.c_str())));
+ ASSERT_NE(receiver, nullptr);
ConnectionId receiverId;
- ASSERT_TRUE((bool)receiver);
- status = mManager->registerSender(receiver, mConnectionId, &receiverId);
+ bool isNew = true;
+ status = mManager->registerSender(receiver, mConnectionId, &receiverId, &isNew);
ASSERT_TRUE(status == ResultStatus::OK);
{
native_handle_t *shandle = nullptr;
@@ -261,7 +273,6 @@
} // anonymous namespace
int main(int argc, char** argv) {
- android::hardware::details::setTrebleTestingOverride(true);
::testing::InitGoogleTest(&argc, argv);
int status = RUN_ALL_TESTS();
LOG(INFO) << "Test result = " << status;
diff --git a/media/bufferpool/aidl/default/tests/multi.cpp b/media/bufferpool/aidl/default/tests/multi.cpp
index 43b0a8c..8806eb0 100644
--- a/media/bufferpool/aidl/default/tests/multi.cpp
+++ b/media/bufferpool/aidl/default/tests/multi.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,34 +18,35 @@
#include <gtest/gtest.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/binder_stability.h>
#include <android-base/logging.h>
-#include <binder/ProcessState.h>
-#include <bufferpool/ClientManager.h>
-#include <hidl/HidlSupport.h>
-#include <hidl/HidlTransportSupport.h>
-#include <hidl/LegacySupport.h>
-#include <hidl/Status.h>
+#include <bufferpool2/ClientManager.h>
+
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
+
#include <iostream>
#include <memory>
#include <vector>
+
#include "allocator.h"
-using android::hardware::configureRpcThreadpool;
-using android::hardware::hidl_handle;
-using android::hardware::media::bufferpool::V2_0::IClientManager;
-using android::hardware::media::bufferpool::V2_0::ResultStatus;
-using android::hardware::media::bufferpool::V2_0::implementation::BufferId;
-using android::hardware::media::bufferpool::V2_0::implementation::ClientManager;
-using android::hardware::media::bufferpool::V2_0::implementation::ConnectionId;
-using android::hardware::media::bufferpool::V2_0::implementation::TransactionId;
-using android::hardware::media::bufferpool::BufferPoolData;
+using aidl::android::hardware::media::bufferpool2::IClientManager;
+using aidl::android::hardware::media::bufferpool2::ResultStatus;
+using aidl::android::hardware::media::bufferpool2::implementation::BufferId;
+using aidl::android::hardware::media::bufferpool2::implementation::ClientManager;
+using aidl::android::hardware::media::bufferpool2::implementation::ConnectionId;
+using aidl::android::hardware::media::bufferpool2::implementation::TransactionId;
+using aidl::android::hardware::media::bufferpool2::BufferPoolData;
namespace {
+const std::string testInstance = std::string() + ClientManager::descriptor + "/multitest";
+
// communication message types between processes.
enum PipeCommand : int32_t {
INIT_OK = 0,
@@ -71,7 +72,7 @@
class BufferpoolMultiTest : public ::testing::Test {
public:
virtual void SetUp() override {
- ResultStatus status;
+ BufferPoolStatus status;
mReceiverPid = -1;
mConnectionValid = false;
@@ -87,7 +88,6 @@
// tearDown
pause();
}
-
mManager = ClientManager::getInstance();
ASSERT_NE(mManager, nullptr);
@@ -116,7 +116,7 @@
RecordProperty("description", description);
}
- android::sp<ClientManager> mManager;
+ std::shared_ptr<ClientManager> mManager;
std::shared_ptr<BufferPoolAllocator> mAllocator;
bool mConnectionValid;
ConnectionId mConnectionId;
@@ -135,7 +135,8 @@
}
void doReceiver() {
- configureRpcThreadpool(1, false);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
PipeMessage message;
mManager = ClientManager::getInstance();
if (!mManager) {
@@ -143,7 +144,11 @@
sendMessage(mResultPipeFds, message);
return;
}
- android::status_t status = mManager->registerAsService();
+ auto binder = mManager->asBinder();
+ AIBinder_forceDowngradeToSystemStability(binder.get());
+ binder_status_t status =
+ AServiceManager_addService(binder.get(), testInstance.c_str());
+ CHECK_EQ(status, STATUS_OK);
if (status != android::OK) {
message.data.command = PipeCommand::INIT_ERROR;
sendMessage(mResultPipeFds, message);
@@ -156,7 +161,7 @@
{
native_handle_t *rhandle = nullptr;
std::shared_ptr<BufferPoolData> rbuffer;
- ResultStatus status = mManager->receive(
+ BufferPoolStatus status = mManager->receive(
message.data.connectionId, message.data.transactionId,
message.data.bufferId, message.data.timestampUs, &rhandle, &rbuffer);
mManager->close(message.data.connectionId);
@@ -182,16 +187,20 @@
// Buffer transfer test between processes.
TEST_F(BufferpoolMultiTest, TransferBuffer) {
- ResultStatus status;
+ BufferPoolStatus status;
PipeMessage message;
ASSERT_TRUE(receiveMessage(mResultPipeFds, &message));
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
- android::sp<IClientManager> receiver = IClientManager::getService();
+ std::shared_ptr<IClientManager> receiver = IClientManager::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService(testInstance.c_str())));
+ ASSERT_NE(receiver, nullptr);
ConnectionId receiverId;
- ASSERT_TRUE((bool)receiver);
- status = mManager->registerSender(receiver, mConnectionId, &receiverId);
+ bool isNew = true;
+ status = mManager->registerSender(receiver, mConnectionId, &receiverId, &isNew);
ASSERT_TRUE(status == ResultStatus::OK);
{
native_handle_t *shandle = nullptr;
@@ -227,7 +236,6 @@
} // anonymous namespace
int main(int argc, char** argv) {
- android::hardware::details::setTrebleTestingOverride(true);
::testing::InitGoogleTest(&argc, argv);
int status = RUN_ALL_TESTS();
LOG(INFO) << "Test result = " << status;
diff --git a/media/bufferpool/aidl/default/tests/single.cpp b/media/bufferpool/aidl/default/tests/single.cpp
index 1e9027b..66aa5e9 100644
--- a/media/bufferpool/aidl/default/tests/single.cpp
+++ b/media/bufferpool/aidl/default/tests/single.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,24 +20,19 @@
#include <android-base/logging.h>
#include <binder/ProcessState.h>
-#include <bufferpool/ClientManager.h>
-#include <hidl/HidlSupport.h>
-#include <hidl/HidlTransportSupport.h>
-#include <hidl/LegacySupport.h>
-#include <hidl/Status.h>
+#include <bufferpool2/ClientManager.h>
#include <unistd.h>
#include <iostream>
#include <memory>
#include <vector>
#include "allocator.h"
-using android::hardware::hidl_handle;
-using android::hardware::media::bufferpool::V2_0::ResultStatus;
-using android::hardware::media::bufferpool::V2_0::implementation::BufferId;
-using android::hardware::media::bufferpool::V2_0::implementation::ClientManager;
-using android::hardware::media::bufferpool::V2_0::implementation::ConnectionId;
-using android::hardware::media::bufferpool::V2_0::implementation::TransactionId;
-using android::hardware::media::bufferpool::BufferPoolData;
+using aidl::android::hardware::media::bufferpool2::implementation::BufferId;
+using aidl::android::hardware::media::bufferpool2::implementation::BufferPoolStatus;
+using aidl::android::hardware::media::bufferpool2::implementation::ClientManager;
+using aidl::android::hardware::media::bufferpool2::implementation::ConnectionId;
+using aidl::android::hardware::media::bufferpool2::implementation::TransactionId;
+using aidl::android::hardware::media::bufferpool2::BufferPoolData;
namespace {
@@ -51,7 +46,7 @@
class BufferpoolSingleTest : public ::testing::Test {
public:
virtual void SetUp() override {
- ResultStatus status;
+ BufferPoolStatus status;
mConnectionValid = false;
mManager = ClientManager::getInstance();
@@ -65,8 +60,9 @@
mConnectionValid = true;
- status = mManager->registerSender(mManager, mConnectionId, &mReceiverId);
- ASSERT_TRUE(status == ResultStatus::ALREADY_EXISTS &&
+ bool isNew = true;
+ status = mManager->registerSender(mManager, mConnectionId, &mReceiverId, &isNew);
+ ASSERT_TRUE(status == ResultStatus::OK && isNew == false &&
mReceiverId == mConnectionId);
}
@@ -81,7 +77,7 @@
RecordProperty("description", description);
}
- android::sp<ClientManager> mManager;
+ std::shared_ptr<ClientManager> mManager;
std::shared_ptr<BufferPoolAllocator> mAllocator;
bool mConnectionValid;
ConnectionId mConnectionId;
@@ -93,7 +89,7 @@
// Check whether each buffer allocation is done successfully with
// unique buffer id.
TEST_F(BufferpoolSingleTest, AllocateBuffer) {
- ResultStatus status;
+ BufferPoolStatus status;
std::vector<uint8_t> vecParams;
getTestAllocatorParams(&vecParams);
@@ -118,7 +114,7 @@
// Buffer recycle test.
// Check whether de-allocated buffers are recycled.
TEST_F(BufferpoolSingleTest, RecycleBuffer) {
- ResultStatus status;
+ BufferPoolStatus status;
std::vector<uint8_t> vecParams;
getTestAllocatorParams(&vecParams);
@@ -143,7 +139,7 @@
// Buffer transfer test.
// Check whether buffer is transferred to another client successfully.
TEST_F(BufferpoolSingleTest, TransferBuffer) {
- ResultStatus status;
+ BufferPoolStatus status;
std::vector<uint8_t> vecParams;
getTestAllocatorParams(&vecParams);
std::shared_ptr<BufferPoolData> sbuffer, rbuffer;
@@ -151,14 +147,14 @@
native_handle_t *recvHandle = nullptr;
TransactionId transactionId;
- int64_t postUs;
+ int64_t postMs;
status = mManager->allocate(mConnectionId, vecParams, &allocHandle, &sbuffer);
ASSERT_TRUE(status == ResultStatus::OK);
ASSERT_TRUE(TestBufferPoolAllocator::Fill(allocHandle, 0x77));
- status = mManager->postSend(mReceiverId, sbuffer, &transactionId, &postUs);
+ status = mManager->postSend(mReceiverId, sbuffer, &transactionId, &postMs);
ASSERT_TRUE(status == ResultStatus::OK);
- status = mManager->receive(mReceiverId, transactionId, sbuffer->mId, postUs,
+ status = mManager->receive(mReceiverId, transactionId, sbuffer->mId, postMs,
&recvHandle, &rbuffer);
EXPECT_TRUE(status == ResultStatus::OK);
ASSERT_TRUE(TestBufferPoolAllocator::Verify(recvHandle, 0x77));