/* * 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 "BufferPoolConnection" #include "Accessor.h" #include "AccessorImpl.h" #include "Connection.h" namespace android { namespace hardware { namespace media { namespace bufferpool { namespace V1_0 { namespace implementation { void ConnectionDeathRecipient::add( int64_t connectionId, const sp<Accessor> &accessor) { std::lock_guard<std::mutex> lock(mLock); if (mAccessors.find(connectionId) == mAccessors.end()) { mAccessors.insert(std::make_pair(connectionId, accessor)); } } void ConnectionDeathRecipient::remove(int64_t connectionId) { std::lock_guard<std::mutex> lock(mLock); mAccessors.erase(connectionId); auto it = mConnectionToCookie.find(connectionId); if (it != mConnectionToCookie.end()) { uint64_t cookie = it->second; mConnectionToCookie.erase(it); auto cit = mCookieToConnections.find(cookie); if (cit != mCookieToConnections.end()) { cit->second.erase(connectionId); if (cit->second.size() == 0) { mCookieToConnections.erase(cit); } } } } void ConnectionDeathRecipient::addCookieToConnection( uint64_t cookie, int64_t connectionId) { std::lock_guard<std::mutex> lock(mLock); if (mAccessors.find(connectionId) == mAccessors.end()) { return; } mConnectionToCookie.insert(std::make_pair(connectionId, cookie)); auto it = mCookieToConnections.find(cookie); if (it != mCookieToConnections.end()) { it->second.insert(connectionId); } else { mCookieToConnections.insert(std::make_pair( cookie, std::set<int64_t>{connectionId})); } } void ConnectionDeathRecipient::serviceDied( uint64_t cookie, const wp<::android::hidl::base::V1_0::IBase>& /* who */ ) { std::map<int64_t, const wp<Accessor>> connectionsToClose; { std::lock_guard<std::mutex> lock(mLock); auto it = mCookieToConnections.find(cookie); if (it != mCookieToConnections.end()) { for (auto conIt = it->second.begin(); conIt != it->second.end(); ++conIt) { auto accessorIt = mAccessors.find(*conIt); if (accessorIt != mAccessors.end()) { connectionsToClose.insert(std::make_pair(*conIt, accessorIt->second)); mAccessors.erase(accessorIt); } mConnectionToCookie.erase(*conIt); } mCookieToConnections.erase(it); } } if (connectionsToClose.size() > 0) { sp<Accessor> accessor; for (auto it = connectionsToClose.begin(); it != connectionsToClose.end(); ++it) { accessor = it->second.promote(); if (accessor) { accessor->close(it->first); ALOGD("connection %lld closed on death", (long long)it->first); } } } } namespace { static sp<ConnectionDeathRecipient> sConnectionDeathRecipient = new ConnectionDeathRecipient(); } sp<ConnectionDeathRecipient> Accessor::getConnectionDeathRecipient() { return sConnectionDeathRecipient; } // Methods from ::android::hardware::media::bufferpool::V1_0::IAccessor follow. Return<void> Accessor::connect(connect_cb _hidl_cb) { sp<Connection> connection; ConnectionId connectionId; const QueueDescriptor* fmqDesc; ResultStatus status = connect(&connection, &connectionId, &fmqDesc, false); if (status == ResultStatus::OK) { _hidl_cb(status, connection, connectionId, *fmqDesc); } else { _hidl_cb(status, nullptr, -1LL, android::hardware::MQDescriptorSync<BufferStatusMessage>( std::vector<android::hardware::GrantorDescriptor>(), nullptr /* nhandle */, 0 /* size */)); } return Void(); } Accessor::Accessor(const std::shared_ptr<BufferPoolAllocator> &allocator) : mImpl(new Impl(allocator)) {} Accessor::~Accessor() { } bool Accessor::isValid() { return (bool)mImpl; } ResultStatus 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); } return ResultStatus::CRITICAL_ERROR; } ResultStatus 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( sp<Connection> *connection, ConnectionId *pConnectionId, const QueueDescriptor** fmqDescPtr, bool local) { if (mImpl) { ResultStatus status = mImpl->connect(this, connection, pConnectionId, fmqDescPtr); if (!local && status == ResultStatus::OK) { sp<Accessor> accessor(this); sConnectionDeathRecipient->add(*pConnectionId, accessor); } return status; } return ResultStatus::CRITICAL_ERROR; } ResultStatus Accessor::close(ConnectionId connectionId) { if (mImpl) { ResultStatus status = mImpl->close(connectionId); sConnectionDeathRecipient->remove(connectionId); return status; } return ResultStatus::CRITICAL_ERROR; } void Accessor::cleanUp(bool clearCache) { if (mImpl) { mImpl->cleanUp(clearCache); } } //IAccessor* HIDL_FETCH_IAccessor(const char* /* name */) { // return new Accessor(); //} } // namespace implementation } // namespace V1_0 } // namespace bufferpool } // namespace media } // namespace hardware } // namespace android