1 /*
2 * Copyright (C) 2007 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 "GraphicBuffer"
17 #include <ui/GraphicBuffer.h>
18 #include <cutils/atomic.h>
19 #include <grallocusage/GrallocUsageConversion.h>
20 #include <ui/DetachedBufferHandle.h>
21 #include <ui/Gralloc2.h>
22 #include <ui/GraphicBufferAllocator.h>
23 #include <ui/GraphicBufferMapper.h>
24 namespace android {
25 // ===========================================================================
26 // Buffer and implementation of ANativeWindowBuffer
27 // ===========================================================================
getUniqueId()28 static uint64_t getUniqueId() {
29 static volatile int32_t nextId = 0;
30 uint64_t id = static_cast<uint64_t>(getpid()) << 32;
31 id |= static_cast<uint32_t>(android_atomic_inc(&nextId));
32 return id;
33 }
from(ANativeWindowBuffer * anwb)34 sp<GraphicBuffer> GraphicBuffer::from(ANativeWindowBuffer* anwb) {
35 return static_cast<GraphicBuffer *>(anwb);
36 }
GraphicBuffer()37 GraphicBuffer::GraphicBuffer()
38 : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
39 mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
40 {
41 width =
42 height =
43 stride =
44 format =
45 usage_deprecated = 0;
46 usage = 0;
47 layerCount = 0;
48 handle = NULL;
49 }
50 // deprecated
GraphicBuffer(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inUsage,std::string requestorName)51 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
52 PixelFormat inFormat, uint32_t inUsage, std::string requestorName)
53 : GraphicBuffer(inWidth, inHeight, inFormat, 1, static_cast<uint64_t>(inUsage), requestorName)
54 {
55 }
GraphicBuffer(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage,std::string requestorName)56 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
57 uint32_t inLayerCount, uint64_t inUsage, std::string requestorName)
58 : GraphicBuffer() {
59 mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage,
60 std::move(requestorName));
61 }
62 // deprecated
GraphicBuffer(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint32_t inUsage,uint32_t inStride,native_handle_t * inHandle,bool keepOwnership)63 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
64 PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage,
65 uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
66 : GraphicBuffer(inHandle, keepOwnership ? TAKE_HANDLE : WRAP_HANDLE,
67 inWidth, inHeight, inFormat, inLayerCount, static_cast<uint64_t>(inUsage),
68 inStride)
69 {
70 }
GraphicBuffer(const native_handle_t * inHandle,HandleWrapMethod method,uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage,uint32_t inStride)71 GraphicBuffer::GraphicBuffer(const native_handle_t* inHandle, HandleWrapMethod method,
72 uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
73 uint32_t inLayerCount, uint64_t inUsage, uint32_t inStride)
74 : GraphicBuffer() {
75 mInitCheck = initWithHandle(inHandle, method, inWidth, inHeight, inFormat, inLayerCount,
76 inUsage, inStride);
77 }
~GraphicBuffer()78 GraphicBuffer::~GraphicBuffer()
79 {
80 if (handle) {
81 free_handle();
82 }
83 }
free_handle()84 void GraphicBuffer::free_handle()
85 {
86 if (mOwner == ownHandle) {
87 mBufferMapper.freeBuffer(handle);
88 } else if (mOwner == ownData) {
89 GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
90 allocator.free(handle);
91 }
92 handle = NULL;
93 }
initCheck() const94 status_t GraphicBuffer::initCheck() const {
95 return static_cast<status_t>(mInitCheck);
96 }
dumpAllocationsToSystemLog()97 void GraphicBuffer::dumpAllocationsToSystemLog()
98 {
99 GraphicBufferAllocator::dumpToSystemLog();
100 }
getNativeBuffer() const101 ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const
102 {
103 return static_cast<ANativeWindowBuffer*>(
104 const_cast<GraphicBuffer*>(this));
105 }
reallocate(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage)106 status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight,
107 PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage)
108 {
109 if (mOwner != ownData)
110 return INVALID_OPERATION;
111 if (handle &&
112 static_cast<int>(inWidth) == width &&
113 static_cast<int>(inHeight) == height &&
114 inFormat == format &&
115 inLayerCount == layerCount &&
116 inUsage == usage)
117 return NO_ERROR;
118 if (handle) {
119 GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
120 allocator.free(handle);
121 handle = 0;
122 }
123 return initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage, "[Reallocation]");
124 }
needsReallocation(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage)125 bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight,
126 PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage)
127 {
128 if (static_cast<int>(inWidth) != width) return true;
129 if (static_cast<int>(inHeight) != height) return true;
130 if (inFormat != format) return true;
131 if (inLayerCount != layerCount) return true;
132 if ((usage & inUsage) != inUsage) return true;
133 return false;
134 }
initWithSize(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage,std::string requestorName)135 status_t GraphicBuffer::initWithSize(uint32_t inWidth, uint32_t inHeight,
136 PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage,
137 std::string requestorName)
138 {
139 GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
140 uint32_t outStride = 0;
141 status_t err = allocator.allocate(inWidth, inHeight, inFormat, inLayerCount,
142 inUsage, &handle, &outStride, mId,
143 std::move(requestorName));
144 if (err == NO_ERROR) {
145 mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
146 width = static_cast<int>(inWidth);
147 height = static_cast<int>(inHeight);
148 format = inFormat;
149 layerCount = inLayerCount;
150 usage = inUsage;
151 usage_deprecated = int(usage);
152 stride = static_cast<int>(outStride);
153 }
154 return err;
155 }
initWithHandle(const native_handle_t * inHandle,HandleWrapMethod method,uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage,uint32_t inStride)156 status_t GraphicBuffer::initWithHandle(const native_handle_t* inHandle, HandleWrapMethod method,
157 uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
158 uint32_t inLayerCount, uint64_t inUsage, uint32_t inStride) {
159 ANativeWindowBuffer::width = static_cast<int>(inWidth);
160 ANativeWindowBuffer::height = static_cast<int>(inHeight);
161 ANativeWindowBuffer::stride = static_cast<int>(inStride);
162 ANativeWindowBuffer::format = inFormat;
163 ANativeWindowBuffer::usage = inUsage;
164 ANativeWindowBuffer::usage_deprecated = int(inUsage);
165 ANativeWindowBuffer::layerCount = inLayerCount;
166 mOwner = (method == WRAP_HANDLE) ? ownNone : ownHandle;
167 if (method == TAKE_UNREGISTERED_HANDLE || method == CLONE_HANDLE) {
168 buffer_handle_t importedHandle;
169 status_t err = mBufferMapper.importBuffer(inHandle, inWidth, inHeight, inLayerCount,
170 inFormat, inUsage, inStride, &importedHandle);
171 if (err != NO_ERROR) {
172 initWithHandle(nullptr, WRAP_HANDLE, 0, 0, 0, 0, 0, 0);
173 return err;
174 }
175 if (method == TAKE_UNREGISTERED_HANDLE) {
176 native_handle_close(inHandle);
177 native_handle_delete(const_cast<native_handle_t*>(inHandle));
178 }
179 inHandle = importedHandle;
180 mBufferMapper.getTransportSize(inHandle, &mTransportNumFds, &mTransportNumInts);
181 }
182 ANativeWindowBuffer::handle = inHandle;
183 return NO_ERROR;
184 }
lock(uint32_t inUsage,void ** vaddr)185 status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr)
186 {
187 const Rect lockBounds(width, height);
188 status_t res = lock(inUsage, lockBounds, vaddr);
189 return res;
190 }
lock(uint32_t inUsage,const Rect & rect,void ** vaddr)191 status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr)
192 {
193 if (rect.left < 0 || rect.right > width ||
194 rect.top < 0 || rect.bottom > height) {
195 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
196 rect.left, rect.top, rect.right, rect.bottom,
197 width, height);
198 return BAD_VALUE;
199 }
200 status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr);
201 return res;
202 }
lockYCbCr(uint32_t inUsage,android_ycbcr * ycbcr)203 status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, android_ycbcr* ycbcr)
204 {
205 const Rect lockBounds(width, height);
206 status_t res = lockYCbCr(inUsage, lockBounds, ycbcr);
207 return res;
208 }
lockYCbCr(uint32_t inUsage,const Rect & rect,android_ycbcr * ycbcr)209 status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, const Rect& rect,
210 android_ycbcr* ycbcr)
211 {
212 if (rect.left < 0 || rect.right > width ||
213 rect.top < 0 || rect.bottom > height) {
214 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
215 rect.left, rect.top, rect.right, rect.bottom,
216 width, height);
217 return BAD_VALUE;
218 }
219 status_t res = getBufferMapper().lockYCbCr(handle, inUsage, rect, ycbcr);
220 return res;
221 }
unlock()222 status_t GraphicBuffer::unlock()
223 {
224 status_t res = getBufferMapper().unlock(handle);
225 return res;
226 }
lockAsync(uint32_t inUsage,void ** vaddr,int fenceFd)227 status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd)
228 {
229 const Rect lockBounds(width, height);
230 status_t res = lockAsync(inUsage, lockBounds, vaddr, fenceFd);
231 return res;
232 }
lockAsync(uint32_t inUsage,const Rect & rect,void ** vaddr,int fenceFd)233 status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect,
234 void** vaddr, int fenceFd)
235 {
236 return lockAsync(inUsage, inUsage, rect, vaddr, fenceFd);
237 }
lockAsync(uint64_t inProducerUsage,uint64_t inConsumerUsage,const Rect & rect,void ** vaddr,int fenceFd)238 status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage,
239 uint64_t inConsumerUsage, const Rect& rect, void** vaddr, int fenceFd)
240 {
241 if (rect.left < 0 || rect.right > width ||
242 rect.top < 0 || rect.bottom > height) {
243 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
244 rect.left, rect.top, rect.right, rect.bottom,
245 width, height);
246 return BAD_VALUE;
247 }
248 status_t res = getBufferMapper().lockAsync(handle, inProducerUsage,
249 inConsumerUsage, rect, vaddr, fenceFd);
250 return res;
251 }
lockAsyncYCbCr(uint32_t inUsage,android_ycbcr * ycbcr,int fenceFd)252 status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, android_ycbcr* ycbcr,
253 int fenceFd)
254 {
255 const Rect lockBounds(width, height);
256 status_t res = lockAsyncYCbCr(inUsage, lockBounds, ycbcr, fenceFd);
257 return res;
258 }
lockAsyncYCbCr(uint32_t inUsage,const Rect & rect,android_ycbcr * ycbcr,int fenceFd)259 status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, const Rect& rect,
260 android_ycbcr* ycbcr, int fenceFd)
261 {
262 if (rect.left < 0 || rect.right > width ||
263 rect.top < 0 || rect.bottom > height) {
264 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
265 rect.left, rect.top, rect.right, rect.bottom,
266 width, height);
267 return BAD_VALUE;
268 }
269 status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect, ycbcr, fenceFd);
270 return res;
271 }
unlockAsync(int * fenceFd)272 status_t GraphicBuffer::unlockAsync(int *fenceFd)
273 {
274 status_t res = getBufferMapper().unlockAsync(handle, fenceFd);
275 return res;
276 }
getFlattenedSize() const277 size_t GraphicBuffer::getFlattenedSize() const {
278 return static_cast<size_t>(13 + (handle ? mTransportNumInts : 0)) * sizeof(int);
279 }
getFdCount() const280 size_t GraphicBuffer::getFdCount() const {
281 return static_cast<size_t>(handle ? mTransportNumFds : 0);
282 }
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const283 status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
284 size_t sizeNeeded = GraphicBuffer::getFlattenedSize();
285 if (size < sizeNeeded) return NO_MEMORY;
286 size_t fdCountNeeded = GraphicBuffer::getFdCount();
287 if (count < fdCountNeeded) return NO_MEMORY;
288 int32_t* buf = static_cast<int32_t*>(buffer);
289 buf[0] = 'GB01';
290 buf[1] = width;
291 buf[2] = height;
292 buf[3] = stride;
293 buf[4] = format;
294 buf[5] = static_cast<int32_t>(layerCount);
295 buf[6] = int(usage); // low 32-bits
296 buf[7] = static_cast<int32_t>(mId >> 32);
297 buf[8] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
298 buf[9] = static_cast<int32_t>(mGenerationNumber);
299 buf[10] = 0;
300 buf[11] = 0;
301 buf[12] = int(usage >> 32); // high 32-bits
302 if (handle) {
303 buf[10] = int32_t(mTransportNumFds);
304 buf[11] = int32_t(mTransportNumInts);
305 memcpy(fds, handle->data, static_cast<size_t>(mTransportNumFds) * sizeof(int));
306 memcpy(buf + 13, handle->data + handle->numFds,
307 static_cast<size_t>(mTransportNumInts) * sizeof(int));
308 }
309 buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded);
310 size -= sizeNeeded;
311 if (handle) {
312 fds += mTransportNumFds;
313 count -= static_cast<size_t>(mTransportNumFds);
314 }
315 return NO_ERROR;
316 }
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)317 status_t GraphicBuffer::unflatten(
318 void const*& buffer, size_t& size, int const*& fds, size_t& count) {
319 if (size < 12 * sizeof(int)) {
320 android_errorWriteLog(0x534e4554, "114223584");
321 return NO_MEMORY;
322 }
323 int const* buf = static_cast<int const*>(buffer);
324 // NOTE: it turns out that some media code generates a flattened GraphicBuffer manually!!!!!
325 // see H2BGraphicBufferProducer.cpp
326 uint32_t flattenWordCount = 0;
327 if (buf[0] == 'GB01') {
328 // new version with 64-bits usage bits
329 flattenWordCount = 13;
330 } else if (buf[0] == 'GBFR') {
331 // old version, when usage bits were 32-bits
332 flattenWordCount = 12;
333 } else {
334 return BAD_TYPE;
335 }
336 const size_t numFds = static_cast<size_t>(buf[10]);
337 const size_t numInts = static_cast<size_t>(buf[11]);
338 // Limit the maxNumber to be relatively small. The number of fds or ints
339 // should not come close to this number, and the number itself was simply
340 // chosen to be high enough to not cause issues and low enough to prevent
341 // overflow problems.
342 const size_t maxNumber = 4096;
343 if (numFds >= maxNumber || numInts >= (maxNumber - flattenWordCount)) {
344 width = height = stride = format = usage_deprecated = 0;
345 layerCount = 0;
346 usage = 0;
347 handle = NULL;
348 ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", numFds, numInts);
349 return BAD_VALUE;
350 }
351 const size_t sizeNeeded = (flattenWordCount + numInts) * sizeof(int);
352 if (size < sizeNeeded) return NO_MEMORY;
353 size_t fdCountNeeded = numFds;
354 if (count < fdCountNeeded) return NO_MEMORY;
355 if (handle) {
356 // free previous handle if any
357 free_handle();
358 }
359 if (numFds || numInts) {
360 width = buf[1];
361 height = buf[2];
362 stride = buf[3];
363 format = buf[4];
364 layerCount = static_cast<uintptr_t>(buf[5]);
365 usage_deprecated = buf[6];
366 if (flattenWordCount == 13) {
367 usage = (uint64_t(buf[12]) << 32) | uint32_t(buf[6]);
368 } else {
369 usage = uint64_t(usage_deprecated);
370 }
371 native_handle* h = native_handle_create(
372 static_cast<int>(numFds), static_cast<int>(numInts));
373 if (!h) {
374 width = height = stride = format = usage_deprecated = 0;
375 layerCount = 0;
376 usage = 0;
377 handle = NULL;
378 ALOGE("unflatten: native_handle_create failed");
379 return NO_MEMORY;
380 }
381 memcpy(h->data, fds, numFds * sizeof(int));
382 memcpy(h->data + numFds, buf + flattenWordCount, numInts * sizeof(int));
383 handle = h;
384 } else {
385 width = height = stride = format = usage_deprecated = 0;
386 layerCount = 0;
387 usage = 0;
388 handle = NULL;
389 }
390 mId = static_cast<uint64_t>(buf[7]) << 32;
391 mId |= static_cast<uint32_t>(buf[8]);
392 mGenerationNumber = static_cast<uint32_t>(buf[9]);
393 mOwner = ownHandle;
394 if (handle != 0) {
395 buffer_handle_t importedHandle;
396 status_t err = mBufferMapper.importBuffer(handle, uint32_t(width), uint32_t(height),
397 uint32_t(layerCount), format, usage, uint32_t(stride), &importedHandle);
398 if (err != NO_ERROR) {
399 width = height = stride = format = usage_deprecated = 0;
400 layerCount = 0;
401 usage = 0;
402 handle = NULL;
403 ALOGE("unflatten: registerBuffer failed: %s (%d)", strerror(-err), err);
404 return err;
405 }
406 native_handle_close(handle);
407 native_handle_delete(const_cast<native_handle_t*>(handle));
408 handle = importedHandle;
409 mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
410 }
411 buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded);
412 size -= sizeNeeded;
413 fds += numFds;
414 count -= numFds;
415 return NO_ERROR;
416 }
isDetachedBuffer() const417 bool GraphicBuffer::isDetachedBuffer() const {
418 return mDetachedBufferHandle && mDetachedBufferHandle->isValid();
419 }
setDetachedBufferHandle(std::unique_ptr<DetachedBufferHandle> channel)420 status_t GraphicBuffer::setDetachedBufferHandle(std::unique_ptr<DetachedBufferHandle> channel) {
421 if (isDetachedBuffer()) {
422 ALOGW("setDetachedBuffer: there is already a BufferHub channel associated with this "
423 "GraphicBuffer. Replacing the old one.");
424 }
425 mDetachedBufferHandle = std::move(channel);
426 return NO_ERROR;
427 }
takeDetachedBufferHandle()428 std::unique_ptr<DetachedBufferHandle> GraphicBuffer::takeDetachedBufferHandle() {
429 return std::move(mDetachedBufferHandle);
430 }
431 // ---------------------------------------------------------------------------
432 }; // namespace android
433