1/*
2 * Copyright 2016 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#ifndef ANDROID_SERVERS_CAMERA3_BUFFER_MANAGER_H
18#define ANDROID_SERVERS_CAMERA3_BUFFER_MANAGER_H
19
20#include <list>
21#include <algorithm>
22#include <ui/GraphicBuffer.h>
23#include <utils/RefBase.h>
24#include <utils/KeyedVector.h>
25#include "Camera3OutputStream.h"
26
27namespace android {
28
29namespace camera3 {
30
31struct StreamInfo;
32class Camera3OutputStream;
33
34/**
35 * A class managing the graphic buffers that is used by camera output streams. It allocates and
36 * hands out Gralloc buffers to the clients (e.g., Camera3OutputStream) based on the requests.
37 * When clients request a buffer, buffer manager will pick a buffer if there are some already
38 * allocated buffer available, will allocate a buffer otherwise. When there are too many allocated
39 * buffer maintained by the buffer manager, it will dynamically deallocate some buffers that are
40 * solely owned by this buffer manager.
41 * In doing so, it reduces the memory footprint unless it is already minimal without impacting
42 * performance.
43 *
44 */
45class Camera3BufferManager: public virtual RefBase {
46public:
47    Camera3BufferManager(const sp<IGraphicBufferAlloc>& allocator = NULL);
48
49    virtual ~Camera3BufferManager();
50
51    /**
52     * This method registers an output stream to this buffer manager by using the provided stream
53     * information.
54     *
55     * The stream info includes the necessary information such as stream size, format, buffer count,
56     * usage flags, etc. for the buffer manager to allocate and hand out buffers for this stream.
57     *
58     * It's illegal to call this method if the stream is not CONFIGURED yet, as some critical
59     * stream properties (e.g., combined usage flags) are only available in this state. It is also
60     * illegal to call this method with an invalid stream set ID (CAMERA3_STREAM_SET_ID_INVALID),
61     * as the invalid stream set ID indicates that this stream doesn't intend to use buffer manager.
62     *
63     *
64     * Once a stream is successfully registered to this buffer manager, the buffer manager takes
65     * over the buffer allocation role and provides buffers to this stream via getBufferForStream().
66     * The returned buffer can be sent to the camera HAL for image output, and then queued to the
67     * ANativeWindow (Surface) for downstream consumer to acquire. Once the image buffer is released
68     * by the consumer end point, the BufferQueueProducer callback onBufferReleased will call
69     * returnBufferForStream() to return the free buffer to this buffer manager. If the stream
70     * uses buffer manager to manage the stream buffers, it should disable the BufferQueue
71     * allocation via IGraphicBufferProducer::allowAllocation(false).
72     *
73     * Registering an already registered stream has no effect.
74     *
75     * Return values:
76     *
77     *  OK:                Registration of the new stream was successful.
78     *  BAD_VALUE:         This stream is not at CONFIGURED state, or the stream ID or stream set
79     *                     ID are invalid, or attempting to register the same stream to multiple
80     *                     stream sets, or other stream properties are invalid.
81     *  INVALID_OPERATION: This buffer manager doesn't support buffer sharing across this stream
82     *                     and other streams that were already registered with the same stream set
83     *                     ID.
84     */
85    status_t registerStream(wp<Camera3OutputStream>& stream, const StreamInfo &streamInfo);
86
87    /**
88     * This method unregisters a stream from this buffer manager.
89     *
90     * After a stream is unregistered, further getBufferForStream() calls will fail for this stream.
91     * After all streams for a given stream set are unregistered, all the buffers solely owned (for
92     * this stream set) by this buffer manager will be freed; all buffers subsequently returned to
93     * this buffer manager for this stream set will be freed immediately.
94     *
95     * Return values:
96     *
97     *  OK:        Removal of the a stream from this buffer manager was successful.
98     *  BAD_VALUE: stream ID or stream set ID are invalid, or stream ID and stream set ID
99     *             combination doesn't match what was registered, or this stream wasn't registered
100     *             to this buffer manager before.
101     */
102    status_t unregisterStream(int streamId, int streamSetId);
103
104    /**
105     * This method obtains a buffer for a stream from this buffer manager.
106     *
107     * This method returns the first free buffer from the free buffer list (associated with this
108     * stream set) if there is any. Otherwise, it will allocate a buffer for this stream, return
109     * it and increment its count of handed-out buffers. When the total number of allocated buffers
110     * is too high, it may deallocate the unused buffers to save memory footprint of this stream
111     * set.
112     *
113     * After this call, the client takes over the ownership of this buffer if it is not freed.
114     *
115     * Return values:
116     *
117     *  OK:        Getting buffer for this stream was successful.
118     *  ALREADY_EXISTS: Enough free buffers are already attached to this output buffer queue,
119     *             user should just dequeue from the buffer queue.
120     *  BAD_VALUE: stream ID or streamSetId are invalid, or stream ID and stream set ID
121     *             combination doesn't match what was registered, or this stream wasn't registered
122     *             to this buffer manager before.
123     *  NO_MEMORY: Unable to allocate a buffer for this stream at this time.
124     */
125    status_t getBufferForStream(int streamId, int streamSetId, sp<GraphicBuffer>* gb, int* fenceFd);
126
127    /**
128     * This method notifies the manager that a buffer has been released by the consumer.
129     *
130     * The buffer is not returned to the buffer manager, but is available for the stream the buffer
131     * is attached to for dequeuing.
132     *
133     * The notification lets the manager know how many buffers are directly available to the stream.
134     *
135     * If onBufferReleased is called for a given released buffer,
136     * returnBufferForStream may not be called for the same buffer, until the
137     * buffer has been reused. The manager will call detachBuffer on the stream
138     * if it needs the released buffer otherwise.
139     *
140     * Return values:
141     *
142     *  OK:        Buffer release was processed succesfully
143     *  BAD_VALUE: stream ID or streamSetId are invalid, or stream ID and stream set ID
144     *             combination doesn't match what was registered, or this stream wasn't registered
145     *             to this buffer manager before.
146     */
147    status_t onBufferReleased(int streamId, int streamSetId);
148
149    /**
150     * This method returns a buffer for a stream to this buffer manager.
151     *
152     * When a buffer is returned, it is treated as a free buffer and may either be reused for future
153     * getBufferForStream() calls, or freed if there total number of outstanding allocated buffers
154     * is too large. The latter only applies to the case where the buffer are physically shared
155     * between streams in the same stream set. A physically shared buffer is the buffer that has one
156     * physical back store but multiple handles. Multiple stream can access the same physical memory
157     * with their own handles. Physically shared buffer can only be supported by Gralloc HAL V1.
158     * See hardware/libhardware/include/hardware/gralloc1.h for more details.
159     *
160     *
161     * This call takes the ownership of the returned buffer if it was allocated by this buffer
162     * manager; clients should not use this buffer after this call. Attempting to access this buffer
163     * after this call will have undefined behavior. Holding a reference to this buffer after this
164     * call may cause memory leakage. If a BufferQueue is used to track the buffers handed out by
165     * this buffer queue, it is recommended to call detachNextBuffer() from the buffer queue after
166     * BufferQueueProducer onBufferReleased callback is fired, and return it to this buffer manager.
167     *
168     *  OK:        Buffer return for this stream was successful.
169     *  BAD_VALUE: stream ID or streamSetId are invalid, or stream ID and stream set ID combination
170     *             doesn't match what was registered, or this stream wasn't registered to this
171     *             buffer manager before.
172     */
173    status_t returnBufferForStream(int streamId, int streamSetId, const sp<GraphicBuffer>& buffer,
174            int fenceFd);
175
176    /**
177     * Dump the buffer manager statistics.
178     */
179    void     dump(int fd, const Vector<String16> &args) const;
180
181private:
182    /**
183     * Lock to synchronize the access to the methods of this class.
184     */
185    mutable Mutex mLock;
186
187    static const size_t kMaxBufferCount = BufferQueueDefs::NUM_BUFFER_SLOTS;
188
189    /**
190     * mAllocator is the connection to SurfaceFlinger that is used to allocate new GraphicBuffer
191     * objects.
192     */
193    sp<IGraphicBufferAlloc> mAllocator;
194
195    struct GraphicBufferEntry {
196        sp<GraphicBuffer> graphicBuffer;
197        int fenceFd;
198        GraphicBufferEntry(const sp<GraphicBuffer>& gb = 0, int fd = -1) :
199            graphicBuffer(gb),
200            fenceFd(fd) {}
201    };
202
203    /**
204     * A buffer entry (indexed by stream ID) represents a single physically allocated buffer. For
205     * Gralloc V0, since each physical buffer is associated with one stream, this is
206     * a single entry map. For Gralloc V1, one physical buffer can be shared between different
207     * streams in one stream set, so this entry may include multiple entries, where the different
208     * graphic buffers have the same common Gralloc backing store.
209     */
210    typedef int StreamId;
211    typedef KeyedVector<StreamId, GraphicBufferEntry> BufferEntry;
212
213    typedef std::list<BufferEntry> BufferList;
214
215    /**
216     * Stream info map (indexed by stream ID) tracks all the streams registered to a particular
217     * stream set.
218     */
219    typedef KeyedVector<StreamId, StreamInfo> InfoMap;
220
221    /**
222     * Stream set buffer count map (indexed by stream ID) tracks all buffer counts of the streams
223     * registered to a particular stream set.
224     */
225    typedef KeyedVector<StreamId, size_t> BufferCountMap;
226
227    /**
228     * StreamSet keeps track of the stream info, free buffer list and hand-out buffer counts for
229     * each stream set.
230     */
231    struct StreamSet {
232        /**
233         * Stream set buffer count water mark representing the max number of allocated buffers
234         * (hand-out buffers + free buffers) count for each stream set. For a given stream set, when
235         * getBufferForStream() is called on this buffer manager, if the total allocated buffer
236         * count exceeds this water mark, the buffer manager will attempt to reduce it as follows:
237         *
238         * In getBufferForStream(), find a buffer associated with other streams (inside the same
239         * stream set) on the free buffer list and free it. For Gralloc V1, can just free the top
240         * of the free buffer list if the physical buffer sharing in this stream is supported.
241         *
242         * For a particular stream set, a larger allocatedBufferWaterMark increases the memory
243         * footprint of the stream set, but reduces the chance that getBufferForStream() will have
244         * to allocate a new buffer. We assume that the streams in one stream set are not streaming
245         * simultaneously, the max allocated buffer count water mark for a stream set will the max
246         * of all streams' total buffer counts. This will avoid new buffer allocation in steady
247         * streaming state.
248         *
249         * This water mark can be dynamically changed, and will grow when the hand-out buffer count
250         * of each stream increases, until it reaches the maxAllowedBufferCount.
251         */
252        size_t allocatedBufferWaterMark;
253
254        /**
255         * The max allowed buffer count for this stream set. It is the max of total number of
256         * buffers for each stream. This is the upper bound of the allocatedBufferWaterMark.
257         */
258        size_t maxAllowedBufferCount;
259
260        /**
261         * The stream info for all streams in this set
262         */
263        InfoMap streamInfoMap;
264        /**
265         * The free buffer list for all the buffers belong to this set. The free buffers are
266         * returned by the returnBufferForStream() call, and available for reuse.
267         */
268        BufferList freeBuffers;
269        /**
270         * The count of the buffers that were handed out to the streams of this set.
271         */
272        BufferCountMap handoutBufferCountMap;
273        /**
274         * The count of the buffers that are attached to the streams of this set.
275         * An attached buffer may be free or handed out
276         */
277        BufferCountMap attachedBufferCountMap;
278
279        StreamSet() {
280            allocatedBufferWaterMark = 0;
281            maxAllowedBufferCount = 0;
282        }
283    };
284
285    /**
286     * Stream set map managed by this buffer manager.
287     */
288    typedef int StreamSetId;
289    KeyedVector<StreamSetId, StreamSet> mStreamSetMap;
290    KeyedVector<StreamId, wp<Camera3OutputStream>> mStreamMap;
291
292    // TODO: There is no easy way to query the Gralloc version in this code yet, we have different
293    // code paths for different Gralloc versions, hardcode something here for now.
294    const uint32_t mGrallocVersion = GRALLOC_DEVICE_API_VERSION_0_1;
295
296    /**
297     * Check if this stream was successfully registered already. This method needs to be called with
298     * mLock held.
299     */
300    bool checkIfStreamRegisteredLocked(int streamId, int streamSetId) const;
301
302    /**
303     * Add a buffer entry to the BufferList. This method needs to be called with mLock held.
304     */
305    status_t addBufferToBufferListLocked(BufferList &bufList, const BufferEntry &buffer);
306
307    /**
308     * Remove all buffers from the BufferList.
309     *
310     * Note that this doesn't mean that the buffers are freed after this call. A buffer is freed
311     * only if all other references to it are dropped.
312     *
313     * This method needs to be called with mLock held.
314     */
315    status_t removeBuffersFromBufferListLocked(BufferList &bufList, int streamId);
316
317    /**
318     * Get the first available buffer from the buffer list for this stream. The graphicBuffer inside
319     * this entry will be NULL if there is no any GraphicBufferEntry found. After this call, the
320     * GraphicBufferEntry will be removed from the BufferList if a GraphicBufferEntry is found.
321     *
322     * This method needs to be called with mLock held.
323     *
324     */
325    GraphicBufferEntry getFirstBufferFromBufferListLocked(BufferList& buffers, int streamId);
326
327    /**
328     * Check if there is any buffer associated with this stream in the given buffer list.
329     *
330     * This method needs to be called with mLock held.
331     *
332     */
333    bool inline hasBufferForStreamLocked(BufferList& buffers, int streamId);
334};
335
336} // namespace camera3
337} // namespace android
338
339#endif // ANDROID_SERVERS_CAMERA3_BUFFER_MANAGER_H
340