1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #define LOG_TAG "BufferPoolConnection" 17 18 #include "Accessor.h" 19 #include "AccessorImpl.h" 20 #include "Connection.h" 21 22 namespace android { 23 namespace hardware { 24 namespace media { 25 namespace bufferpool { 26 namespace V1_0 { 27 namespace implementation { 28 29 void ConnectionDeathRecipient::add( 30 int64_t connectionId, 31 const sp<Accessor> &accessor) { 32 std::lock_guard<std::mutex> lock(mLock); 33 if (mAccessors.find(connectionId) == mAccessors.end()) { 34 mAccessors.insert(std::make_pair(connectionId, accessor)); 35 } 36 } 37 38 void ConnectionDeathRecipient::remove(int64_t connectionId) { 39 std::lock_guard<std::mutex> lock(mLock); 40 mAccessors.erase(connectionId); 41 auto it = mConnectionToCookie.find(connectionId); 42 if (it != mConnectionToCookie.end()) { 43 uint64_t cookie = it->second; 44 mConnectionToCookie.erase(it); 45 auto cit = mCookieToConnections.find(cookie); 46 if (cit != mCookieToConnections.end()) { 47 cit->second.erase(connectionId); 48 if (cit->second.size() == 0) { 49 mCookieToConnections.erase(cit); 50 } 51 } 52 } 53 } 54 55 void ConnectionDeathRecipient::addCookieToConnection( 56 uint64_t cookie, 57 int64_t connectionId) { 58 std::lock_guard<std::mutex> lock(mLock); 59 if (mAccessors.find(connectionId) == mAccessors.end()) { 60 return; 61 } 62 mConnectionToCookie.insert(std::make_pair(connectionId, cookie)); 63 auto it = mCookieToConnections.find(cookie); 64 if (it != mCookieToConnections.end()) { 65 it->second.insert(connectionId); 66 } else { 67 mCookieToConnections.insert(std::make_pair( 68 cookie, std::set<int64_t>{connectionId})); 69 } 70 } 71 72 void ConnectionDeathRecipient::serviceDied( 73 uint64_t cookie, 74 const wp<::android::hidl::base::V1_0::IBase>& /* who */ 75 ) { 76 std::map<int64_t, const wp<Accessor>> connectionsToClose; 77 { 78 std::lock_guard<std::mutex> lock(mLock); 79 80 auto it = mCookieToConnections.find(cookie); 81 if (it != mCookieToConnections.end()) { 82 for (auto conIt = it->second.begin(); conIt != it->second.end(); ++conIt) { 83 auto accessorIt = mAccessors.find(*conIt); 84 if (accessorIt != mAccessors.end()) { 85 connectionsToClose.insert(std::make_pair(*conIt, accessorIt->second)); 86 mAccessors.erase(accessorIt); 87 } 88 mConnectionToCookie.erase(*conIt); 89 } 90 mCookieToConnections.erase(it); 91 } 92 } 93 94 if (connectionsToClose.size() > 0) { 95 sp<Accessor> accessor; 96 for (auto it = connectionsToClose.begin(); it != connectionsToClose.end(); ++it) { 97 accessor = it->second.promote(); 98 99 if (accessor) { 100 accessor->close(it->first); 101 ALOGD("connection %lld closed on death", (long long)it->first); 102 } 103 } 104 } 105 } 106 107 namespace { 108 static sp<ConnectionDeathRecipient> sConnectionDeathRecipient = 109 new ConnectionDeathRecipient(); 110 } 111 112 sp<ConnectionDeathRecipient> Accessor::getConnectionDeathRecipient() { 113 return sConnectionDeathRecipient; 114 } 115 116 // Methods from ::android::hardware::media::bufferpool::V1_0::IAccessor follow. 117 Return<void> Accessor::connect(connect_cb _hidl_cb) { 118 sp<Connection> connection; 119 ConnectionId connectionId; 120 const QueueDescriptor* fmqDesc; 121 122 ResultStatus status = connect(&connection, &connectionId, &fmqDesc, false); 123 if (status == ResultStatus::OK) { 124 _hidl_cb(status, connection, connectionId, *fmqDesc); 125 } else { 126 _hidl_cb(status, nullptr, -1LL, 127 android::hardware::MQDescriptorSync<BufferStatusMessage>( 128 std::vector<android::hardware::GrantorDescriptor>(), 129 nullptr /* nhandle */, 0 /* size */)); 130 } 131 return Void(); 132 } 133 134 Accessor::Accessor(const std::shared_ptr<BufferPoolAllocator> &allocator) 135 : mImpl(new Impl(allocator)) {} 136 137 Accessor::~Accessor() { 138 } 139 140 bool Accessor::isValid() { 141 return (bool)mImpl; 142 } 143 144 ResultStatus Accessor::allocate( 145 ConnectionId connectionId, 146 const std::vector<uint8_t> ¶ms, 147 BufferId *bufferId, const native_handle_t** handle) { 148 if (mImpl) { 149 return mImpl->allocate(connectionId, params, bufferId, handle); 150 } 151 return ResultStatus::CRITICAL_ERROR; 152 } 153 154 ResultStatus Accessor::fetch( 155 ConnectionId connectionId, TransactionId transactionId, 156 BufferId bufferId, const native_handle_t** handle) { 157 if (mImpl) { 158 return mImpl->fetch(connectionId, transactionId, bufferId, handle); 159 } 160 return ResultStatus::CRITICAL_ERROR; 161 } 162 163 ResultStatus Accessor::connect( 164 sp<Connection> *connection, ConnectionId *pConnectionId, 165 const QueueDescriptor** fmqDescPtr, bool local) { 166 if (mImpl) { 167 ResultStatus status = mImpl->connect(this, connection, pConnectionId, fmqDescPtr); 168 if (!local && status == ResultStatus::OK) { 169 sp<Accessor> accessor(this); 170 sConnectionDeathRecipient->add(*pConnectionId, accessor); 171 } 172 return status; 173 } 174 return ResultStatus::CRITICAL_ERROR; 175 } 176 177 ResultStatus Accessor::close(ConnectionId connectionId) { 178 if (mImpl) { 179 ResultStatus status = mImpl->close(connectionId); 180 sConnectionDeathRecipient->remove(connectionId); 181 return status; 182 } 183 return ResultStatus::CRITICAL_ERROR; 184 } 185 186 void Accessor::cleanUp(bool clearCache) { 187 if (mImpl) { 188 mImpl->cleanUp(clearCache); 189 } 190 } 191 192 //IAccessor* HIDL_FETCH_IAccessor(const char* /* name */) { 193 // return new Accessor(); 194 //} 195 196 } // namespace implementation 197 } // namespace V1_0 198 } // namespace bufferpool 199 } // namespace media 200 } // namespace hardware 201 } // namespace android 202