• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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