1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <aidl/android/hardware/media/bufferpool2/BnAccessor.h> 20 #include <aidl/android/hardware/media/bufferpool2/IObserver.h> 21 #include <bufferpool2/BufferPoolTypes.h> 22 23 #include <memory> 24 #include <map> 25 #include <set> 26 #include <condition_variable> 27 28 #include "BufferPool.h" 29 30 namespace aidl::android::hardware::media::bufferpool2::implementation { 31 32 struct Connection; 33 using ::aidl::android::hardware::media::bufferpool2::IObserver; 34 using ::aidl::android::hardware::media::bufferpool2::IAccessor; 35 36 /** 37 * Receives death notifications from remote connections. 38 * On death notifications, the connections are closed and used resources 39 * are released. 40 */ 41 struct ConnectionDeathRecipient { 42 ConnectionDeathRecipient(); 43 /** 44 * Registers a newly connected connection from remote processes. 45 */ 46 void add(int64_t connectionId, const std::shared_ptr<Accessor> &accessor); 47 48 /** 49 * Removes a connection. 50 */ 51 void remove(int64_t connectionId); 52 53 void addCookieToConnection(void *cookie, int64_t connectionId); 54 55 void onDead(void *cookie); 56 57 AIBinder_DeathRecipient *getRecipient(); 58 59 private: 60 ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; 61 62 std::mutex mLock; 63 std::map<void *, std::set<int64_t>> mCookieToConnections; 64 std::map<int64_t, void *> mConnectionToCookie; 65 std::map<int64_t, const std::weak_ptr<Accessor>> mAccessors; 66 }; 67 68 /** 69 * A buffer pool accessor which enables a buffer pool to communicate with buffer 70 * pool clients. 1:1 correspondense holds between a buffer pool and an accessor. 71 */ 72 struct Accessor : public BnAccessor { 73 // Methods from ::aidl::android::hardware::media::bufferpool2::IAccessor. 74 ::ndk::ScopedAStatus connect(const std::shared_ptr<IObserver>& in_observer, 75 IAccessor::ConnectionInfo* _aidl_return) override; 76 77 /** 78 * Creates a buffer pool accessor which uses the specified allocator. 79 * 80 * @param allocator buffer allocator. 81 */ 82 explicit Accessor(const std::shared_ptr<BufferPoolAllocator> &allocator); 83 84 /** Destructs a buffer pool accessor. */ 85 ~Accessor(); 86 87 /** Returns whether the accessor is valid. */ 88 bool isValid(); 89 90 /** Invalidates all buffers which are owned by bufferpool */ 91 BufferPoolStatus flush(); 92 93 /** Allocates a buffer from a buffer pool. 94 * 95 * @param connectionId the connection id of the client. 96 * @param params the allocation parameters. 97 * @param bufferId the id of the allocated buffer. 98 * @param handle the native handle of the allocated buffer. 99 * 100 * @return OK when a buffer is successfully allocated. 101 * NO_MEMORY when there is no memory. 102 * CRITICAL_ERROR otherwise. 103 */ 104 BufferPoolStatus allocate( 105 ConnectionId connectionId, 106 const std::vector<uint8_t>& params, 107 BufferId *bufferId, 108 const native_handle_t** handle); 109 110 /** 111 * Fetches a buffer for the specified transaction. 112 * 113 * @param connectionId the id of receiving connection(client). 114 * @param transactionId the id of the transfer transaction. 115 * @param bufferId the id of the buffer to be fetched. 116 * @param handle the native handle of the fetched buffer. 117 * 118 * @return OK when a buffer is successfully fetched. 119 * NO_MEMORY when there is no memory. 120 * CRITICAL_ERROR otherwise. 121 */ 122 BufferPoolStatus fetch( 123 ConnectionId connectionId, 124 TransactionId transactionId, 125 BufferId bufferId, 126 const native_handle_t** handle); 127 128 /** 129 * Makes a connection to the buffer pool. The buffer pool client uses the 130 * created connection in order to communicate with the buffer pool. An 131 * FMQ for buffer status message is also created for the client. 132 * 133 * @param observer client observer for buffer invalidation 134 * @param local true when a connection request comes from local process, 135 * false otherwise. 136 * @param connection created connection 137 * @param pConnectionId the id of the created connection 138 * @param pMsgId the id of the recent buffer pool message 139 * @param statusDescPtr FMQ descriptor for shared buffer status message 140 * queue between a buffer pool and the client. 141 * @param invDescPtr FMQ descriptor for buffer invalidation message 142 * queue from a buffer pool to the client. 143 * 144 * @return OK when a connection is successfully made. 145 * NO_MEMORY when there is no memory. 146 * CRITICAL_ERROR otherwise. 147 */ 148 BufferPoolStatus connect( 149 const std::shared_ptr<IObserver>& observer, 150 bool local, 151 std::shared_ptr<Connection> *connection, ConnectionId *pConnectionId, 152 uint32_t *pMsgId, 153 StatusDescriptor* statusDescPtr, 154 InvalidationDescriptor* invDescPtr); 155 156 /** 157 * Closes the specified connection to the client. 158 * 159 * @param connectionId the id of the connection. 160 * 161 * @return OK when the connection is closed. 162 * CRITICAL_ERROR otherwise. 163 */ 164 BufferPoolStatus close(ConnectionId connectionId); 165 166 /** 167 * Processes pending buffer status messages and performs periodic cache 168 * cleaning. 169 * 170 * @param clearCache if clearCache is true, it frees all buffers waiting 171 * to be recycled. 172 */ 173 void cleanUp(bool clearCache); 174 175 /** 176 * ACK on buffer invalidation messages 177 */ 178 void handleInvalidateAck(); 179 180 /** 181 * Gets a death_recipient for remote connection death. 182 */ 183 static std::shared_ptr<ConnectionDeathRecipient> getConnectionDeathRecipient(); 184 185 static void createInvalidator(); 186 187 static void createEvictor(); 188 189 private: 190 // ConnectionId = pid : (timestamp_created + seqId) 191 // in order to guarantee uniqueness for each connection 192 struct ConnectionIdGenerator { 193 int32_t mPid; 194 uint32_t mSeqId; 195 std::mutex mLock; 196 197 ConnectionIdGenerator(); 198 ConnectionId getConnectionId(); 199 }; 200 201 const std::shared_ptr<BufferPoolAllocator> mAllocator; 202 nsecs_t mScheduleEvictTs; 203 BufferPool mBufferPool; 204 205 struct AccessorInvalidator { 206 std::map<uint32_t, const std::weak_ptr<Accessor>> mAccessors; 207 std::mutex mMutex; 208 std::condition_variable mCv; 209 bool mReady; 210 211 AccessorInvalidator(); 212 void addAccessor(uint32_t accessorId, const std::weak_ptr<Accessor> &accessor); 213 void delAccessor(uint32_t accessorId); 214 }; 215 216 static std::unique_ptr<AccessorInvalidator> sInvalidator; 217 218 static void invalidatorThread( 219 std::map<uint32_t, const std::weak_ptr<Accessor>> &accessors, 220 std::mutex &mutex, 221 std::condition_variable &cv, 222 bool &ready); 223 224 struct AccessorEvictor { 225 std::map<const std::weak_ptr<Accessor>, nsecs_t, std::owner_less<>> mAccessors; 226 std::mutex mMutex; 227 std::condition_variable mCv; 228 229 AccessorEvictor(); 230 void addAccessor(const std::weak_ptr<Accessor> &accessor, nsecs_t ts); 231 }; 232 233 static std::unique_ptr<AccessorEvictor> sEvictor; 234 235 static void evictorThread( 236 std::map<const std::weak_ptr<Accessor>, nsecs_t, std::owner_less<>> &accessors, 237 std::mutex &mutex, 238 std::condition_variable &cv); 239 240 void scheduleEvictIfNeeded(); 241 242 friend struct BufferPool; 243 }; 244 245 } // namespace aidl::android::hardware::media::bufferpool2::implementation 246