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