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