1 /*
2  * Copyright 2014 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_GUI_BUFFERQUEUECORE_H
18 #define ANDROID_GUI_BUFFERQUEUECORE_H
19 
20 #include <gui/BufferItem.h>
21 #include <gui/BufferQueueDefs.h>
22 #include <gui/BufferSlot.h>
23 #include <gui/OccupancyTracker.h>
24 
25 #include <utils/NativeHandle.h>
26 #include <utils/RefBase.h>
27 #include <utils/String8.h>
28 #include <utils/StrongPointer.h>
29 #include <utils/Trace.h>
30 #include <utils/Vector.h>
31 
32 #include <list>
33 #include <set>
34 #include <mutex>
35 #include <condition_variable>
36 
37 #define ATRACE_BUFFER_INDEX(index)                                                         \
38     do {                                                                                   \
39         if (ATRACE_ENABLED()) {                                                            \
40             char ___traceBuf[1024];                                                        \
41             snprintf(___traceBuf, 1024, "%s: %d", mCore->mConsumerName.string(), (index)); \
42             android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf);                    \
43         }                                                                                  \
44     } while (false)
45 
46 namespace android {
47 
48 class IConsumerListener;
49 class IProducerListener;
50 
51 class BufferQueueCore : public virtual RefBase {
52 
53     friend class BufferQueueProducer;
54     friend class BufferQueueConsumer;
55 
56 public:
57     // Used as a placeholder slot number when the value isn't pointing to an
58     // existing buffer.
59     enum { INVALID_BUFFER_SLOT = BufferItem::INVALID_BUFFER_SLOT };
60 
61     // We reserve two slots in order to guarantee that the producer and
62     // consumer can run asynchronously.
63     enum { MAX_MAX_ACQUIRED_BUFFERS = BufferQueueDefs::NUM_BUFFER_SLOTS - 2 };
64 
65     enum {
66         // The API number used to indicate the currently connected producer
67         CURRENTLY_CONNECTED_API = -1,
68 
69         // The API number used to indicate that no producer is connected
70         NO_CONNECTED_API        = 0,
71     };
72 
73     typedef Vector<BufferItem> Fifo;
74 
75     // BufferQueueCore manages a pool of gralloc memory slots to be used by
76     // producers and consumers.
77     BufferQueueCore();
78     virtual ~BufferQueueCore();
79 
80 private:
81     // Dump our state in a string
82     void dumpState(const String8& prefix, String8* outResult) const;
83 
84     // getMinUndequeuedBufferCountLocked returns the minimum number of buffers
85     // that must remain in a state other than DEQUEUED. The async parameter
86     // tells whether we're in asynchronous mode.
87     int getMinUndequeuedBufferCountLocked() const;
88 
89     // getMinMaxBufferCountLocked returns the minimum number of buffers allowed
90     // given the current BufferQueue state. The async parameter tells whether
91     // we're in asynchonous mode.
92     int getMinMaxBufferCountLocked() const;
93 
94     // getMaxBufferCountLocked returns the maximum number of buffers that can be
95     // allocated at once. This value depends on the following member variables:
96     //
97     //     mMaxDequeuedBufferCount
98     //     mMaxAcquiredBufferCount
99     //     mMaxBufferCount
100     //     mAsyncMode
101     //     mDequeueBufferCannotBlock
102     //
103     // Any time one of these member variables is changed while a producer is
104     // connected, mDequeueCondition must be broadcast.
105     int getMaxBufferCountLocked() const;
106 
107     // This performs the same computation but uses the given arguments instead
108     // of the member variables for mMaxBufferCount, mAsyncMode, and
109     // mDequeueBufferCannotBlock.
110     int getMaxBufferCountLocked(bool asyncMode,
111             bool dequeueBufferCannotBlock, int maxBufferCount) const;
112 
113     // clearBufferSlotLocked frees the GraphicBuffer and sync resources for the
114     // given slot.
115     void clearBufferSlotLocked(int slot);
116 
117     // freeAllBuffersLocked frees the GraphicBuffer and sync resources for
118     // all slots, even if they're currently dequeued, queued, or acquired.
119     void freeAllBuffersLocked();
120 
121     // discardFreeBuffersLocked releases all currently-free buffers held by the
122     // queue, in order to reduce the memory consumption of the queue to the
123     // minimum possible without discarding data.
124     void discardFreeBuffersLocked();
125 
126     // If delta is positive, makes more slots available. If negative, takes
127     // away slots. Returns false if the request can't be met.
128     bool adjustAvailableSlotsLocked(int delta);
129 
130     // waitWhileAllocatingLocked blocks until mIsAllocating is false.
131     void waitWhileAllocatingLocked(std::unique_lock<std::mutex>& lock) const;
132 
133 #if DEBUG_ONLY_CODE
134     // validateConsistencyLocked ensures that the free lists are in sync with
135     // the information stored in mSlots
136     void validateConsistencyLocked() const;
137 #endif
138 
139     // mMutex is the mutex used to prevent concurrent access to the member
140     // variables of BufferQueueCore objects. It must be locked whenever any
141     // member variable is accessed.
142     mutable std::mutex mMutex;
143 
144     // mIsAbandoned indicates that the BufferQueue will no longer be used to
145     // consume image buffers pushed to it using the IGraphicBufferProducer
146     // interface. It is initialized to false, and set to true in the
147     // consumerDisconnect method. A BufferQueue that is abandoned will return
148     // the NO_INIT error from all IGraphicBufferProducer methods capable of
149     // returning an error.
150     bool mIsAbandoned;
151 
152     // mConsumerControlledByApp indicates whether the connected consumer is
153     // controlled by the application.
154     bool mConsumerControlledByApp;
155 
156     // mConsumerName is a string used to identify the BufferQueue in log
157     // messages. It is set by the IGraphicBufferConsumer::setConsumerName
158     // method.
159     String8 mConsumerName;
160 
161     // mConsumerListener is used to notify the connected consumer of
162     // asynchronous events that it may wish to react to. It is initially
163     // set to NULL and is written by consumerConnect and consumerDisconnect.
164     sp<IConsumerListener> mConsumerListener;
165 
166     // mConsumerUsageBits contains flags that the consumer wants for
167     // GraphicBuffers.
168     uint64_t mConsumerUsageBits;
169 
170     // mConsumerIsProtected indicates the consumer is ready to handle protected
171     // buffer.
172     bool mConsumerIsProtected;
173 
174     // mConnectedApi indicates the producer API that is currently connected
175     // to this BufferQueue. It defaults to NO_CONNECTED_API, and gets updated
176     // by the connect and disconnect methods.
177     int mConnectedApi;
178     // PID of the process which last successfully called connect(...)
179     pid_t mConnectedPid;
180 
181     // mLinkedToDeath is used to set a binder death notification on
182     // the producer.
183     sp<IProducerListener> mLinkedToDeath;
184 
185     // mConnectedProducerListener is used to handle the onBufferReleased
186     // and onBuffersDiscarded notification.
187     sp<IProducerListener> mConnectedProducerListener;
188     // mBufferReleasedCbEnabled is used to indicate whether onBufferReleased()
189     // callback is registered by the listener. When set to false,
190     // mConnectedProducerListener will not trigger onBufferReleased() callback.
191     bool mBufferReleasedCbEnabled;
192 
193     // mSlots is an array of buffer slots that must be mirrored on the producer
194     // side. This allows buffer ownership to be transferred between the producer
195     // and consumer without sending a GraphicBuffer over Binder. The entire
196     // array is initialized to NULL at construction time, and buffers are
197     // allocated for a slot when requestBuffer is called with that slot's index.
198     BufferQueueDefs::SlotsType mSlots;
199 
200     // mQueue is a FIFO of queued buffers used in synchronous mode.
201     Fifo mQueue;
202 
203     // mFreeSlots contains all of the slots which are FREE and do not currently
204     // have a buffer attached.
205     std::set<int> mFreeSlots;
206 
207     // mFreeBuffers contains all of the slots which are FREE and currently have
208     // a buffer attached.
209     std::list<int> mFreeBuffers;
210 
211     // mUnusedSlots contains all slots that are currently unused. They should be
212     // free and not have a buffer attached.
213     std::list<int> mUnusedSlots;
214 
215     // mActiveBuffers contains all slots which have a non-FREE buffer attached.
216     std::set<int> mActiveBuffers;
217 
218     // mDequeueCondition is a condition variable used for dequeueBuffer in
219     // synchronous mode.
220     mutable std::condition_variable mDequeueCondition;
221 
222     // mDequeueBufferCannotBlock indicates whether dequeueBuffer is allowed to
223     // block. This flag is set during connect when both the producer and
224     // consumer are controlled by the application.
225     bool mDequeueBufferCannotBlock;
226 
227     // mQueueBufferCanDrop indicates whether queueBuffer is allowed to drop
228     // buffers in non-async mode. This flag is set during connect when both the
229     // producer and consumer are controlled by application.
230     bool mQueueBufferCanDrop;
231 
232     // mLegacyBufferDrop indicates whether mQueueBufferCanDrop is in effect.
233     // If this flag is set mQueueBufferCanDrop is working as explained. If not
234     // queueBuffer will not drop buffers unless consumer is SurfaceFlinger and
235     // mQueueBufferCanDrop is set.
236     bool mLegacyBufferDrop;
237 
238     // mDefaultBufferFormat can be set so it will override the buffer format
239     // when it isn't specified in dequeueBuffer.
240     PixelFormat mDefaultBufferFormat;
241 
242     // mDefaultWidth holds the default width of allocated buffers. It is used
243     // in dequeueBuffer if a width and height of 0 are specified.
244     uint32_t mDefaultWidth;
245 
246     // mDefaultHeight holds the default height of allocated buffers. It is used
247     // in dequeueBuffer if a width and height of 0 are specified.
248     uint32_t mDefaultHeight;
249 
250     // mDefaultBufferDataSpace holds the default dataSpace of queued buffers.
251     // It is used in queueBuffer if a dataspace of 0 (HAL_DATASPACE_UNKNOWN)
252     // is specified.
253     android_dataspace mDefaultBufferDataSpace;
254 
255     // mMaxBufferCount is the limit on the number of buffers that will be
256     // allocated at one time. This limit can be set by the consumer.
257     int mMaxBufferCount;
258 
259     // mMaxAcquiredBufferCount is the number of buffers that the consumer may
260     // acquire at one time. It defaults to 1, and can be changed by the consumer
261     // via setMaxAcquiredBufferCount, but this may only be done while no
262     // producer is connected to the BufferQueue. This value is used to derive
263     // the value returned for the MIN_UNDEQUEUED_BUFFERS query to the producer.
264     int mMaxAcquiredBufferCount;
265 
266     // mMaxDequeuedBufferCount is the number of buffers that the producer may
267     // dequeue at one time. It defaults to 1, and can be changed by the producer
268     // via setMaxDequeuedBufferCount.
269     int mMaxDequeuedBufferCount;
270 
271     // mBufferHasBeenQueued is true once a buffer has been queued. It is reset
272     // when something causes all buffers to be freed (e.g., changing the buffer
273     // count).
274     bool mBufferHasBeenQueued;
275 
276     // mFrameCounter is the free running counter, incremented on every
277     // successful queueBuffer call and buffer allocation.
278     uint64_t mFrameCounter;
279 
280     // mTransformHint is used to optimize for screen rotations.
281     uint32_t mTransformHint;
282 
283     // mSidebandStream is a handle to the sideband buffer stream, if any
284     sp<NativeHandle> mSidebandStream;
285 
286     // mIsAllocating indicates whether a producer is currently trying to allocate buffers (which
287     // releases mMutex while doing the allocation proper). Producers should not modify any of the
288     // FREE slots while this is true. mIsAllocatingCondition is signaled when this value changes to
289     // false.
290     bool mIsAllocating;
291 
292     // mIsAllocatingCondition is a condition variable used by producers to wait until mIsAllocating
293     // becomes false.
294     mutable std::condition_variable mIsAllocatingCondition;
295 
296     // mAllowAllocation determines whether dequeueBuffer is allowed to allocate
297     // new buffers
298     bool mAllowAllocation;
299 
300     // mBufferAge tracks the age of the contents of the most recently dequeued
301     // buffer as the number of frames that have elapsed since it was last queued
302     uint64_t mBufferAge;
303 
304     // mGenerationNumber stores the current generation number of the attached
305     // producer. Any attempt to attach a buffer with a different generation
306     // number will fail.
307     uint32_t mGenerationNumber;
308 
309     // mAsyncMode indicates whether or not async mode is enabled.
310     // In async mode an extra buffer will be allocated to allow the producer to
311     // enqueue buffers without blocking.
312     bool mAsyncMode;
313 
314     // mSharedBufferMode indicates whether or not shared buffer mode is enabled.
315     bool mSharedBufferMode;
316 
317     // When shared buffer mode is enabled, this indicates whether the consumer
318     // should acquire buffers even if BufferQueue doesn't indicate that they are
319     // available.
320     bool mAutoRefresh;
321 
322     // When shared buffer mode is enabled, this tracks which slot contains the
323     // shared buffer.
324     int mSharedBufferSlot;
325 
326     // Cached data about the shared buffer in shared buffer mode
327     struct SharedBufferCache {
SharedBufferCacheSharedBufferCache328         SharedBufferCache(Rect _crop, uint32_t _transform,
329                 uint32_t _scalingMode, android_dataspace _dataspace)
330         : crop(_crop),
331           transform(_transform),
332           scalingMode(_scalingMode),
333           dataspace(_dataspace) {
334         }
335 
336         Rect crop;
337         uint32_t transform;
338         uint32_t scalingMode;
339         android_dataspace dataspace;
340     } mSharedBufferCache;
341 
342     // The slot of the last queued buffer
343     int mLastQueuedSlot;
344 
345     OccupancyTracker mOccupancyTracker;
346 
347     const uint64_t mUniqueId;
348 
349     // When buffer size is driven by the consumer and mTransformHint specifies
350     // a 90 or 270 degree rotation, this indicates whether the width and height
351     // used by dequeueBuffer will be additionally swapped.
352     bool mAutoPrerotation;
353 
354     // mTransformHintInUse is to cache the mTransformHint used by the producer.
355     uint32_t mTransformHintInUse;
356 
357 }; // class BufferQueueCore
358 
359 } // namespace android
360 
361 #endif
362