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
17 #define LOG_TAG "GraphicBuffer"
18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19
20 #include <ui/GraphicBuffer.h>
21
22 #include <cutils/atomic.h>
23
24 #include <grallocusage/GrallocUsageConversion.h>
25 #include <sync/sync.h>
26 #include <ui/GraphicBufferAllocator.h>
27 #include <ui/GraphicBufferMapper.h>
28 #include <utils/Trace.h>
29
30 namespace android {
31
32 // ===========================================================================
33 // Buffer and implementation of ANativeWindowBuffer
34 // ===========================================================================
35
getUniqueId()36 static uint64_t getUniqueId() {
37 static volatile int32_t nextId = 0;
38 uint64_t id = static_cast<uint64_t>(getpid()) << 32;
39 id |= static_cast<uint32_t>(android_atomic_inc(&nextId));
40 return id;
41 }
42
resolveLegacyByteLayoutFromPlaneLayout(const std::vector<ui::PlaneLayout> & planeLayouts,int32_t * outBytesPerPixel,int32_t * outBytesPerStride)43 static void resolveLegacyByteLayoutFromPlaneLayout(const std::vector<ui::PlaneLayout>& planeLayouts,
44 int32_t* outBytesPerPixel,
45 int32_t* outBytesPerStride) {
46 if (planeLayouts.empty()) return;
47 if (outBytesPerPixel) {
48 int32_t bitsPerPixel = planeLayouts.front().sampleIncrementInBits;
49 for (const auto& planeLayout : planeLayouts) {
50 if (bitsPerPixel != planeLayout.sampleIncrementInBits) {
51 bitsPerPixel = -1;
52 }
53 }
54 if (bitsPerPixel >= 0 && bitsPerPixel % 8 == 0) {
55 *outBytesPerPixel = bitsPerPixel / 8;
56 } else {
57 *outBytesPerPixel = -1;
58 }
59 }
60 if (outBytesPerStride) {
61 int32_t bytesPerStride = planeLayouts.front().strideInBytes;
62 for (const auto& planeLayout : planeLayouts) {
63 if (bytesPerStride != planeLayout.strideInBytes) {
64 bytesPerStride = -1;
65 }
66 }
67 if (bytesPerStride >= 0) {
68 *outBytesPerStride = bytesPerStride;
69 } else {
70 *outBytesPerStride = -1;
71 }
72 }
73 }
74
from(ANativeWindowBuffer * anwb)75 sp<GraphicBuffer> GraphicBuffer::from(ANativeWindowBuffer* anwb) {
76 return static_cast<GraphicBuffer *>(anwb);
77 }
78
fromAHardwareBuffer(AHardwareBuffer * buffer)79 GraphicBuffer* GraphicBuffer::fromAHardwareBuffer(AHardwareBuffer* buffer) {
80 return reinterpret_cast<GraphicBuffer*>(buffer);
81 }
82
fromAHardwareBuffer(AHardwareBuffer const * buffer)83 GraphicBuffer const* GraphicBuffer::fromAHardwareBuffer(AHardwareBuffer const* buffer) {
84 return reinterpret_cast<GraphicBuffer const*>(buffer);
85 }
86
toAHardwareBuffer()87 AHardwareBuffer* GraphicBuffer::toAHardwareBuffer() {
88 return reinterpret_cast<AHardwareBuffer*>(this);
89 }
90
toAHardwareBuffer() const91 AHardwareBuffer const* GraphicBuffer::toAHardwareBuffer() const {
92 return reinterpret_cast<AHardwareBuffer const*>(this);
93 }
94
GraphicBuffer()95 GraphicBuffer::GraphicBuffer()
96 : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
97 mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
98 {
99 width =
100 height =
101 stride =
102 format =
103 usage_deprecated = 0;
104 usage = 0;
105 layerCount = 0;
106 handle = nullptr;
107 }
108
109 // deprecated
GraphicBuffer(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inUsage,std::string requestorName)110 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
111 PixelFormat inFormat, uint32_t inUsage, std::string requestorName)
112 : GraphicBuffer(inWidth, inHeight, inFormat, 1, static_cast<uint64_t>(inUsage), requestorName)
113 {
114 }
115
GraphicBuffer(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage,std::string requestorName)116 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
117 uint32_t inLayerCount, uint64_t inUsage, std::string requestorName)
118 : GraphicBuffer() {
119 mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage,
120 std::move(requestorName));
121 }
122
123 // 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)124 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
125 PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage,
126 uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
127 : GraphicBuffer(inHandle, keepOwnership ? TAKE_HANDLE : WRAP_HANDLE,
128 inWidth, inHeight, inFormat, inLayerCount, static_cast<uint64_t>(inUsage),
129 inStride)
130 {
131 }
132
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)133 GraphicBuffer::GraphicBuffer(const native_handle_t* inHandle, HandleWrapMethod method,
134 uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
135 uint32_t inLayerCount, uint64_t inUsage, uint32_t inStride)
136 : GraphicBuffer() {
137 mInitCheck = initWithHandle(inHandle, method, inWidth, inHeight, inFormat, inLayerCount,
138 inUsage, inStride);
139 }
140
GraphicBuffer(const GraphicBufferAllocator::AllocationRequest & request)141 GraphicBuffer::GraphicBuffer(const GraphicBufferAllocator::AllocationRequest& request)
142 : GraphicBuffer() {
143 GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
144 auto result = allocator.allocate(request);
145 mInitCheck = result.status;
146 if (result.status == NO_ERROR) {
147 handle = result.handle;
148 stride = result.stride;
149
150 mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
151
152 width = static_cast<int>(request.width);
153 height = static_cast<int>(request.height);
154 format = request.format;
155 layerCount = request.layerCount;
156 usage = request.usage;
157 usage_deprecated = int(usage);
158 }
159 }
160
~GraphicBuffer()161 GraphicBuffer::~GraphicBuffer()
162 {
163 ATRACE_CALL();
164 if (handle) {
165 free_handle();
166 }
167 for (auto& [callback, context] : mDeathCallbacks) {
168 callback(context, mId);
169 }
170 }
171
free_handle()172 void GraphicBuffer::free_handle()
173 {
174 if (mOwner == ownHandle) {
175 mBufferMapper.freeBuffer(handle);
176 } else if (mOwner == ownData) {
177 GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
178 allocator.free(handle);
179 }
180 handle = nullptr;
181 }
182
initCheck() const183 status_t GraphicBuffer::initCheck() const {
184 return static_cast<status_t>(mInitCheck);
185 }
186
dumpAllocationsToSystemLog()187 void GraphicBuffer::dumpAllocationsToSystemLog()
188 {
189 GraphicBufferAllocator::dumpToSystemLog();
190 }
191
getNativeBuffer() const192 ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const
193 {
194 return static_cast<ANativeWindowBuffer*>(
195 const_cast<GraphicBuffer*>(this));
196 }
197
getDataspace(ui::Dataspace * outDataspace) const198 status_t GraphicBuffer::getDataspace(ui::Dataspace* outDataspace) const {
199 return mBufferMapper.getDataspace(handle, outDataspace);
200 }
201
reallocate(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage)202 status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight,
203 PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage)
204 {
205 if (mOwner != ownData)
206 return INVALID_OPERATION;
207
208 if (handle &&
209 static_cast<int>(inWidth) == width &&
210 static_cast<int>(inHeight) == height &&
211 inFormat == format &&
212 inLayerCount == layerCount &&
213 inUsage == usage)
214 return NO_ERROR;
215
216 if (handle) {
217 GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
218 allocator.free(handle);
219 handle = nullptr;
220 }
221 return initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage, "[Reallocation]");
222 }
223
needsReallocation(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage)224 bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight,
225 PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage)
226 {
227 if (static_cast<int>(inWidth) != width) return true;
228 if (static_cast<int>(inHeight) != height) return true;
229 if (inFormat != format) return true;
230 if (inLayerCount != layerCount) return true;
231 if ((usage & inUsage) != inUsage) return true;
232 if ((usage & USAGE_PROTECTED) != (inUsage & USAGE_PROTECTED)) return true;
233 return false;
234 }
235
initWithSize(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage,std::string requestorName)236 status_t GraphicBuffer::initWithSize(uint32_t inWidth, uint32_t inHeight,
237 PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage,
238 std::string requestorName)
239 {
240 GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
241 uint32_t outStride = 0;
242 status_t err = allocator.allocate(inWidth, inHeight, inFormat, inLayerCount,
243 inUsage, &handle, &outStride, mId,
244 std::move(requestorName));
245 if (err == NO_ERROR) {
246 mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
247
248 width = static_cast<int>(inWidth);
249 height = static_cast<int>(inHeight);
250 format = inFormat;
251 layerCount = inLayerCount;
252 usage = inUsage;
253 usage_deprecated = int(usage);
254 stride = static_cast<int>(outStride);
255 }
256 return err;
257 }
258
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)259 status_t GraphicBuffer::initWithHandle(const native_handle_t* inHandle, HandleWrapMethod method,
260 uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
261 uint32_t inLayerCount, uint64_t inUsage, uint32_t inStride) {
262 ANativeWindowBuffer::width = static_cast<int>(inWidth);
263 ANativeWindowBuffer::height = static_cast<int>(inHeight);
264 ANativeWindowBuffer::stride = static_cast<int>(inStride);
265 ANativeWindowBuffer::format = inFormat;
266 ANativeWindowBuffer::usage = inUsage;
267 ANativeWindowBuffer::usage_deprecated = int(inUsage);
268
269 ANativeWindowBuffer::layerCount = inLayerCount;
270
271 mOwner = (method == WRAP_HANDLE) ? ownNone : ownHandle;
272
273 if (method == TAKE_UNREGISTERED_HANDLE || method == CLONE_HANDLE) {
274 buffer_handle_t importedHandle;
275 status_t err = mBufferMapper.importBuffer(inHandle, inWidth, inHeight, inLayerCount,
276 inFormat, inUsage, inStride, &importedHandle);
277 if (err != NO_ERROR) {
278 initWithHandle(nullptr, WRAP_HANDLE, 0, 0, 0, 0, 0, 0);
279
280 return err;
281 }
282
283 if (method == TAKE_UNREGISTERED_HANDLE) {
284 native_handle_close(inHandle);
285 native_handle_delete(const_cast<native_handle_t*>(inHandle));
286 }
287
288 inHandle = importedHandle;
289 mBufferMapper.getTransportSize(inHandle, &mTransportNumFds, &mTransportNumInts);
290 }
291
292 ANativeWindowBuffer::handle = inHandle;
293
294 return NO_ERROR;
295 }
296
lock(uint32_t inUsage,void ** vaddr,int32_t * outBytesPerPixel,int32_t * outBytesPerStride)297 status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr, int32_t* outBytesPerPixel,
298 int32_t* outBytesPerStride) {
299 const Rect lockBounds(width, height);
300 status_t res = lock(inUsage, lockBounds, vaddr, outBytesPerPixel, outBytesPerStride);
301 return res;
302 }
303
lock(uint32_t inUsage,const Rect & rect,void ** vaddr,int32_t * outBytesPerPixel,int32_t * outBytesPerStride)304 status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr,
305 int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
306 if (rect.left < 0 || rect.right > width ||
307 rect.top < 0 || rect.bottom > height) {
308 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
309 rect.left, rect.top, rect.right, rect.bottom,
310 width, height);
311 return BAD_VALUE;
312 }
313
314 return lockAsync(inUsage, rect, vaddr, -1, outBytesPerPixel, outBytesPerStride);
315 }
316
lockYCbCr(uint32_t inUsage,android_ycbcr * ycbcr)317 status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, android_ycbcr* ycbcr)
318 {
319 const Rect lockBounds(width, height);
320 status_t res = lockYCbCr(inUsage, lockBounds, ycbcr);
321 return res;
322 }
323
lockYCbCr(uint32_t inUsage,const Rect & rect,android_ycbcr * ycbcr)324 status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, const Rect& rect,
325 android_ycbcr* ycbcr)
326 {
327 if (rect.left < 0 || rect.right > width ||
328 rect.top < 0 || rect.bottom > height) {
329 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
330 rect.left, rect.top, rect.right, rect.bottom,
331 width, height);
332 return BAD_VALUE;
333 }
334 return lockAsyncYCbCr(inUsage, rect, ycbcr, -1);
335 }
336
unlock()337 status_t GraphicBuffer::unlock()
338 {
339 return unlockAsync(nullptr);
340 }
341
lockAsync(uint32_t inUsage,void ** vaddr,int fenceFd,int32_t * outBytesPerPixel,int32_t * outBytesPerStride)342 status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd,
343 int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
344 const Rect lockBounds(width, height);
345 status_t res =
346 lockAsync(inUsage, lockBounds, vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
347 return res;
348 }
349
lockAsync(uint32_t inUsage,const Rect & rect,void ** vaddr,int fenceFd,int32_t * outBytesPerPixel,int32_t * outBytesPerStride)350 status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr, int fenceFd,
351 int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
352 return lockAsync(inUsage, inUsage, rect, vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
353 }
354
lockAsync(uint64_t inProducerUsage,uint64_t inConsumerUsage,const Rect & rect,void ** vaddr,int fenceFd,int32_t * outBytesPerPixel,int32_t * outBytesPerStride)355 status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage, uint64_t inConsumerUsage,
356 const Rect& rect, void** vaddr, int fenceFd,
357 int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
358 if (rect.left < 0 || rect.right > width ||
359 rect.top < 0 || rect.bottom > height) {
360 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
361 rect.left, rect.top, rect.right, rect.bottom,
362 width, height);
363 return BAD_VALUE;
364 }
365
366 // Resolve the bpp & bps before doing a lock in case this fails we don't have to worry about
367 // doing an unlock
368 int32_t legacyBpp = -1, legacyBps = -1;
369 if (outBytesPerPixel || outBytesPerStride) {
370 const auto mapperVersion = getBufferMapperVersion();
371 // For gralloc2 we need to guess at the bpp & bps
372 // For gralloc3 the lock() call will return it
373 // For gralloc4 & later the PlaneLayout metadata query is vastly superior and we
374 // resolve bpp & bps just for compatibility
375
376 // TODO: See if we can't just remove gralloc2 support.
377 if (mapperVersion == GraphicBufferMapper::GRALLOC_2) {
378 legacyBpp = bytesPerPixel(format);
379 if (legacyBpp > 0) {
380 legacyBps = stride * legacyBpp;
381 } else {
382 legacyBpp = -1;
383 }
384 } else if (mapperVersion >= GraphicBufferMapper::GRALLOC_4) {
385 auto planeLayout = getBufferMapper().getPlaneLayouts(handle);
386 if (!planeLayout.has_value()) return planeLayout.asStatus();
387 resolveLegacyByteLayoutFromPlaneLayout(planeLayout.value(), &legacyBpp, &legacyBps);
388 }
389 }
390
391 const uint64_t usage = static_cast<uint64_t>(
392 android_convertGralloc1To0Usage(inProducerUsage, inConsumerUsage));
393
394 auto result = getBufferMapper().lock(handle, usage, rect, base::unique_fd{fenceFd});
395
396 if (!result.has_value()) {
397 return result.error().asStatus();
398 }
399 auto value = result.value();
400 *vaddr = value.address;
401
402 if (outBytesPerPixel) {
403 *outBytesPerPixel = legacyBpp != -1 ? legacyBpp : value.bytesPerPixel;
404 }
405 if (outBytesPerStride) {
406 *outBytesPerStride = legacyBps != -1 ? legacyBps : value.bytesPerStride;
407 }
408 return OK;
409 }
410
lockAsyncYCbCr(uint32_t inUsage,android_ycbcr * ycbcr,int fenceFd)411 status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, android_ycbcr* ycbcr,
412 int fenceFd)
413 {
414 const Rect lockBounds(width, height);
415 status_t res = lockAsyncYCbCr(inUsage, lockBounds, ycbcr, fenceFd);
416 return res;
417 }
418
lockAsyncYCbCr(uint32_t inUsage,const Rect & rect,android_ycbcr * ycbcr,int fenceFd)419 status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, const Rect& rect,
420 android_ycbcr* ycbcr, int fenceFd)
421 {
422 if (rect.left < 0 || rect.right > width ||
423 rect.top < 0 || rect.bottom > height) {
424 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
425 rect.left, rect.top, rect.right, rect.bottom,
426 width, height);
427 return BAD_VALUE;
428 }
429 auto result = getBufferMapper().lockYCbCr(handle, static_cast<int64_t>(inUsage), rect,
430 base::unique_fd{fenceFd});
431 if (!result.has_value()) {
432 return result.error().asStatus();
433 }
434 *ycbcr = result.value();
435 return OK;
436 }
437
unlockAsync(int * fenceFd)438 status_t GraphicBuffer::unlockAsync(int *fenceFd)
439 {
440 return getBufferMapper().unlockAsync(handle, fenceFd);
441 }
442
isSupported(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage,bool * outSupported) const443 status_t GraphicBuffer::isSupported(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
444 uint32_t inLayerCount, uint64_t inUsage,
445 bool* outSupported) const {
446 return mBufferMapper.isSupported(inWidth, inHeight, inFormat, inLayerCount, inUsage,
447 outSupported);
448 }
449
getFlattenedSize() const450 size_t GraphicBuffer::getFlattenedSize() const {
451 return static_cast<size_t>(13 + (handle ? mTransportNumInts : 0)) * sizeof(int);
452 }
453
getFdCount() const454 size_t GraphicBuffer::getFdCount() const {
455 return static_cast<size_t>(handle ? mTransportNumFds : 0);
456 }
457
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const458 status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
459 size_t sizeNeeded = GraphicBuffer::getFlattenedSize();
460 if (size < sizeNeeded) return NO_MEMORY;
461
462 size_t fdCountNeeded = GraphicBuffer::getFdCount();
463 if (count < fdCountNeeded) return NO_MEMORY;
464
465 int32_t* buf = static_cast<int32_t*>(buffer);
466 buf[0] = 'GB01';
467 buf[1] = width;
468 buf[2] = height;
469 buf[3] = stride;
470 buf[4] = format;
471 buf[5] = static_cast<int32_t>(layerCount);
472 buf[6] = int(usage); // low 32-bits
473 buf[7] = static_cast<int32_t>(mId >> 32);
474 buf[8] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
475 buf[9] = static_cast<int32_t>(mGenerationNumber);
476 buf[10] = 0;
477 buf[11] = 0;
478 buf[12] = int(usage >> 32); // high 32-bits
479
480 if (handle) {
481 buf[10] = int32_t(mTransportNumFds);
482 buf[11] = int32_t(mTransportNumInts);
483 memcpy(fds, handle->data, static_cast<size_t>(mTransportNumFds) * sizeof(int));
484 memcpy(buf + 13, handle->data + handle->numFds,
485 static_cast<size_t>(mTransportNumInts) * sizeof(int));
486 }
487
488 buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded);
489 size -= sizeNeeded;
490 if (handle) {
491 fds += mTransportNumFds;
492 count -= static_cast<size_t>(mTransportNumFds);
493 }
494 return NO_ERROR;
495 }
496
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)497 status_t GraphicBuffer::unflatten(void const*& buffer, size_t& size, int const*& fds,
498 size_t& count) {
499 // Check if size is not smaller than buf[0] is supposed to take.
500 if (size < sizeof(int)) {
501 return NO_MEMORY;
502 }
503
504 int const* buf = static_cast<int const*>(buffer);
505
506 // NOTE: it turns out that some media code generates a flattened GraphicBuffer manually!!!!!
507 // see H2BGraphicBufferProducer.cpp
508 uint32_t flattenWordCount = 0;
509 if (buf[0] == 'GB01') {
510 // new version with 64-bits usage bits
511 flattenWordCount = 13;
512 } else if (buf[0] == 'GBFR') {
513 // old version, when usage bits were 32-bits
514 flattenWordCount = 12;
515 } else {
516 return BAD_TYPE;
517 }
518
519 if (size < 12 * sizeof(int)) {
520 android_errorWriteLog(0x534e4554, "114223584");
521 return NO_MEMORY;
522 }
523
524 const size_t numFds = static_cast<size_t>(buf[10]);
525 const size_t numInts = static_cast<size_t>(buf[11]);
526
527 // Limit the maxNumber to be relatively small. The number of fds or ints
528 // should not come close to this number, and the number itself was simply
529 // chosen to be high enough to not cause issues and low enough to prevent
530 // overflow problems.
531 const size_t maxNumber = 4096;
532 if (numFds >= maxNumber || numInts >= (maxNumber - flattenWordCount)) {
533 width = height = stride = format = usage_deprecated = 0;
534 layerCount = 0;
535 usage = 0;
536 handle = nullptr;
537 ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", numFds, numInts);
538 return BAD_VALUE;
539 }
540
541 const size_t sizeNeeded = (flattenWordCount + numInts) * sizeof(int);
542 if (size < sizeNeeded) return NO_MEMORY;
543
544 size_t fdCountNeeded = numFds;
545 if (count < fdCountNeeded) return NO_MEMORY;
546
547 if (handle) {
548 // free previous handle if any
549 free_handle();
550 }
551
552 if (numFds || numInts) {
553 width = buf[1];
554 height = buf[2];
555 stride = buf[3];
556 format = buf[4];
557 layerCount = static_cast<uintptr_t>(buf[5]);
558 usage_deprecated = buf[6];
559 if (flattenWordCount == 13) {
560 usage = (uint64_t(buf[12]) << 32) | uint32_t(buf[6]);
561 } else {
562 usage = uint64_t(ANDROID_NATIVE_UNSIGNED_CAST(usage_deprecated));
563 }
564 native_handle* h =
565 native_handle_create(static_cast<int>(numFds), static_cast<int>(numInts));
566 if (!h) {
567 width = height = stride = format = usage_deprecated = 0;
568 layerCount = 0;
569 usage = 0;
570 handle = nullptr;
571 ALOGE("unflatten: native_handle_create failed");
572 return NO_MEMORY;
573 }
574 memcpy(h->data, fds, numFds * sizeof(int));
575 memcpy(h->data + numFds, buf + flattenWordCount, numInts * sizeof(int));
576 handle = h;
577 } else {
578 width = height = stride = format = usage_deprecated = 0;
579 layerCount = 0;
580 usage = 0;
581 handle = nullptr;
582 }
583
584 mId = static_cast<uint64_t>(buf[7]) << 32;
585 mId |= static_cast<uint32_t>(buf[8]);
586
587 mGenerationNumber = static_cast<uint32_t>(buf[9]);
588
589 mOwner = ownHandle;
590
591 if (handle != nullptr) {
592 buffer_handle_t importedHandle;
593 status_t err = mBufferMapper.importBuffer(handle, uint32_t(width), uint32_t(height),
594 uint32_t(layerCount), format, usage, uint32_t(stride), &importedHandle);
595 if (err != NO_ERROR) {
596 width = height = stride = format = usage_deprecated = 0;
597 layerCount = 0;
598 usage = 0;
599 handle = nullptr;
600 ALOGE("unflatten: registerBuffer failed: %s (%d)", strerror(-err), err);
601 return err;
602 }
603
604 native_handle_close(handle);
605 native_handle_delete(const_cast<native_handle_t*>(handle));
606 handle = importedHandle;
607 mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
608 }
609
610 buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded);
611 size -= sizeNeeded;
612 fds += numFds;
613 count -= numFds;
614 return NO_ERROR;
615 }
616
addDeathCallback(GraphicBufferDeathCallback deathCallback,void * context)617 void GraphicBuffer::addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context) {
618 mDeathCallbacks.emplace_back(deathCallback, context);
619 }
620
621 // ---------------------------------------------------------------------------
622
623 }; // namespace android
624