blob: c4d8f76ec708f07903c69cd51a1abca0c96b722d [file] [log] [blame]
Mathias Agopian3330b202009-10-05 17:07:12 -07001/*
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
Mathias Agopian98e71dd2010-02-11 17:30:52 -080017#define LOG_TAG "GraphicBuffer"
18
Mathias Agopian3330b202009-10-05 17:07:12 -070019#include <ui/GraphicBuffer.h>
Mathias Agopian311b4792017-02-28 15:00:49 -080020
21#include <cutils/atomic.h>
22
Mathias Agopianfe2f54f2017-02-15 19:48:58 -080023#include <ui/GrallocMapper.h>
Mathias Agopian3330b202009-10-05 17:07:12 -070024#include <ui/GraphicBufferAllocator.h>
25#include <ui/GraphicBufferMapper.h>
Mathias Agopian3330b202009-10-05 17:07:12 -070026
Mathias Agopian3330b202009-10-05 17:07:12 -070027namespace android {
28
29// ===========================================================================
Iliyan Malchev697526b2011-05-01 11:33:26 -070030// Buffer and implementation of ANativeWindowBuffer
Mathias Agopian3330b202009-10-05 17:07:12 -070031// ===========================================================================
32
Dan Stozab1363d32014-03-28 15:10:52 -070033static uint64_t getUniqueId() {
34 static volatile int32_t nextId = 0;
35 uint64_t id = static_cast<uint64_t>(getpid()) << 32;
36 id |= static_cast<uint32_t>(android_atomic_inc(&nextId));
37 return id;
38}
39
Mathias Agopian3330b202009-10-05 17:07:12 -070040GraphicBuffer::GraphicBuffer()
Mathias Agopian54ba51d2009-10-26 20:12:37 -070041 : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
Pablo Ceballos53390e12015-08-04 11:25:59 -070042 mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
Dan Stozab1363d32014-03-28 15:10:52 -070043{
Dan Stoza01049c82014-11-11 10:32:31 -080044 width =
45 height =
46 stride =
47 format =
Mathias Agopian3330b202009-10-05 17:07:12 -070048 usage = 0;
Mathias Agopian841abed2017-02-10 16:15:34 -080049 layerCount = 0;
Mathias Agopian3330b202009-10-05 17:07:12 -070050 handle = NULL;
51}
52
Dan Stozad3182402014-11-17 12:03:59 -080053GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
Dan Stoza024e9312016-08-24 12:17:29 -070054 PixelFormat inFormat, uint32_t inUsage, std::string requestorName)
Mathias Agopian54ba51d2009-10-26 20:12:37 -070055 : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
Pablo Ceballos53390e12015-08-04 11:25:59 -070056 mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
Mathias Agopian3330b202009-10-05 17:07:12 -070057{
Dan Stoza01049c82014-11-11 10:32:31 -080058 width =
59 height =
60 stride =
61 format =
Mathias Agopian3330b202009-10-05 17:07:12 -070062 usage = 0;
Mathias Agopian841abed2017-02-10 16:15:34 -080063 layerCount = 0;
Mathias Agopian3330b202009-10-05 17:07:12 -070064 handle = NULL;
Craig Donnere96a3252017-02-02 12:13:34 -080065 mInitCheck = initSize(inWidth, inHeight, inFormat, 1, inUsage, inUsage,
Dan Stoza024e9312016-08-24 12:17:29 -070066 std::move(requestorName));
Mathias Agopian3330b202009-10-05 17:07:12 -070067}
68
Dan Stozad3182402014-11-17 12:03:59 -080069GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
Craig Donnere96a3252017-02-02 12:13:34 -080070 PixelFormat inFormat, uint32_t inLayerCount, uint64_t producerUsage,
71 uint64_t consumerUsage, std::string requestorName)
Craig Donner6ebc46a2016-10-21 15:23:44 -070072 : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
73 mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
74{
75 width =
76 height =
77 stride =
78 format =
Craig Donner6ebc46a2016-10-21 15:23:44 -070079 usage = 0;
Mathias Agopian841abed2017-02-10 16:15:34 -080080 layerCount = 0;
Craig Donner6ebc46a2016-10-21 15:23:44 -070081 handle = NULL;
Craig Donnere96a3252017-02-02 12:13:34 -080082 mInitCheck = initSize(inWidth, inHeight, inFormat, inLayerCount,
83 producerUsage, consumerUsage, std::move(requestorName));
Craig Donner6ebc46a2016-10-21 15:23:44 -070084}
85
86GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
87 PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage,
88 uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
Mathias Agopian54ba51d2009-10-26 20:12:37 -070089 : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
90 mBufferMapper(GraphicBufferMapper::get()),
Pablo Ceballos53390e12015-08-04 11:25:59 -070091 mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
Mathias Agopian54ba51d2009-10-26 20:12:37 -070092{
Dan Stozad3182402014-11-17 12:03:59 -080093 width = static_cast<int>(inWidth);
94 height = static_cast<int>(inHeight);
95 stride = static_cast<int>(inStride);
Mathias Agopian54ba51d2009-10-26 20:12:37 -070096 format = inFormat;
Craig Donner6ebc46a2016-10-21 15:23:44 -070097 layerCount = inLayerCount;
Dan Stozad3182402014-11-17 12:03:59 -080098 usage = static_cast<int>(inUsage);
Mathias Agopian54ba51d2009-10-26 20:12:37 -070099 handle = inHandle;
100}
101
Daniel Nicoara1c457102017-02-07 17:27:25 -0500102GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
103 PixelFormat inFormat, uint32_t inLayerCount, uint32_t inProducerUsage,
104 uint32_t inConsumerUsage, uint32_t inStride,
105 native_handle_t* inHandle, bool keepOwnership)
106 : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
107 mBufferMapper(GraphicBufferMapper::get()),
108 mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
109{
110 width = static_cast<int>(inWidth);
111 height = static_cast<int>(inHeight);
112 stride = static_cast<int>(inStride);
113 format = inFormat;
114 layerCount = inLayerCount;
115 usage = static_cast<int>(inConsumerUsage | inProducerUsage);
116 handle = inHandle;
117}
118
119
Iliyan Malchev697526b2011-05-01 11:33:26 -0700120GraphicBuffer::GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership)
Jamie Gennis309d3bb2010-10-07 13:46:55 -0700121 : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
122 mBufferMapper(GraphicBufferMapper::get()),
Pablo Ceballos53390e12015-08-04 11:25:59 -0700123 mInitCheck(NO_ERROR), mWrappedBuffer(buffer), mId(getUniqueId()),
124 mGenerationNumber(0)
Jamie Gennis309d3bb2010-10-07 13:46:55 -0700125{
126 width = buffer->width;
127 height = buffer->height;
128 stride = buffer->stride;
129 format = buffer->format;
Craig Donner6ebc46a2016-10-21 15:23:44 -0700130 layerCount = buffer->layerCount;
Jamie Gennis309d3bb2010-10-07 13:46:55 -0700131 usage = buffer->usage;
132 handle = buffer->handle;
133}
134
Mathias Agopian3330b202009-10-05 17:07:12 -0700135GraphicBuffer::~GraphicBuffer()
136{
137 if (handle) {
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800138 free_handle();
139 }
140}
141
142void GraphicBuffer::free_handle()
143{
144 if (mOwner == ownHandle) {
Jamie Gennis309d3bb2010-10-07 13:46:55 -0700145 mBufferMapper.unregisterBuffer(handle);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800146 if (!mBufferMapper.getGrallocMapper().valid()) {
147 native_handle_close(handle);
148 native_handle_delete(const_cast<native_handle*>(handle));
149 }
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800150 } else if (mOwner == ownData) {
151 GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
152 allocator.free(handle);
Mathias Agopian3330b202009-10-05 17:07:12 -0700153 }
Praveen Chavan22e4cc32015-09-16 11:20:00 -0700154 handle = NULL;
Jamie Gennis309d3bb2010-10-07 13:46:55 -0700155 mWrappedBuffer = 0;
Mathias Agopian3330b202009-10-05 17:07:12 -0700156}
157
158status_t GraphicBuffer::initCheck() const {
Dan Stoza133caac2014-12-01 15:15:31 -0800159 return static_cast<status_t>(mInitCheck);
Mathias Agopian3330b202009-10-05 17:07:12 -0700160}
161
Mathias Agopian678bdd62010-12-03 17:33:09 -0800162void GraphicBuffer::dumpAllocationsToSystemLog()
163{
164 GraphicBufferAllocator::dumpToSystemLog();
165}
166
Iliyan Malchev697526b2011-05-01 11:33:26 -0700167ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const
Mathias Agopian3330b202009-10-05 17:07:12 -0700168{
Colin Cross18fae752014-07-22 15:55:08 -0700169 LOG_ALWAYS_FATAL_IF(this == NULL, "getNativeBuffer() called on NULL GraphicBuffer");
Iliyan Malchev697526b2011-05-01 11:33:26 -0700170 return static_cast<ANativeWindowBuffer*>(
Mathias Agopian3330b202009-10-05 17:07:12 -0700171 const_cast<GraphicBuffer*>(this));
172}
173
Dan Stozad3182402014-11-17 12:03:59 -0800174status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight,
Craig Donner6ebc46a2016-10-21 15:23:44 -0700175 PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage)
Mathias Agopian3330b202009-10-05 17:07:12 -0700176{
Mathias Agopian54ba51d2009-10-26 20:12:37 -0700177 if (mOwner != ownData)
178 return INVALID_OPERATION;
179
Dan Stozad3182402014-11-17 12:03:59 -0800180 if (handle &&
181 static_cast<int>(inWidth) == width &&
182 static_cast<int>(inHeight) == height &&
183 inFormat == format &&
Craig Donner6ebc46a2016-10-21 15:23:44 -0700184 inLayerCount == layerCount &&
Dan Stozad3182402014-11-17 12:03:59 -0800185 static_cast<int>(inUsage) == usage)
Mathias Agopian579b3f82010-06-08 19:54:15 -0700186 return NO_ERROR;
187
Mathias Agopian3330b202009-10-05 17:07:12 -0700188 if (handle) {
189 GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
190 allocator.free(handle);
191 handle = 0;
192 }
Craig Donnere96a3252017-02-02 12:13:34 -0800193 return initSize(inWidth, inHeight, inFormat, inLayerCount, inUsage, inUsage,
Craig Donner6ebc46a2016-10-21 15:23:44 -0700194 "[Reallocation]");
Mathias Agopian3330b202009-10-05 17:07:12 -0700195}
196
Dan Stoza9de72932015-04-16 17:28:43 -0700197bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight,
Craig Donner6ebc46a2016-10-21 15:23:44 -0700198 PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage)
Dan Stoza9de72932015-04-16 17:28:43 -0700199{
200 if (static_cast<int>(inWidth) != width) return true;
201 if (static_cast<int>(inHeight) != height) return true;
202 if (inFormat != format) return true;
Craig Donner6ebc46a2016-10-21 15:23:44 -0700203 if (inLayerCount != layerCount) return true;
Dan Stoza9de72932015-04-16 17:28:43 -0700204 if ((static_cast<uint32_t>(usage) & inUsage) != inUsage) return true;
205 return false;
206}
207
Dan Stozad3182402014-11-17 12:03:59 -0800208status_t GraphicBuffer::initSize(uint32_t inWidth, uint32_t inHeight,
Craig Donnere96a3252017-02-02 12:13:34 -0800209 PixelFormat inFormat, uint32_t inLayerCount, uint64_t inProducerUsage,
210 uint64_t inConsumerUsage, std::string requestorName)
Mathias Agopian3330b202009-10-05 17:07:12 -0700211{
Mathias Agopian3330b202009-10-05 17:07:12 -0700212 GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
Dan Stozad3182402014-11-17 12:03:59 -0800213 uint32_t outStride = 0;
Craig Donner6ebc46a2016-10-21 15:23:44 -0700214 status_t err = allocator.allocate(inWidth, inHeight, inFormat, inLayerCount,
Craig Donnere96a3252017-02-02 12:13:34 -0800215 inProducerUsage, inConsumerUsage, &handle, &outStride, mId,
216 std::move(requestorName));
Mathias Agopian3330b202009-10-05 17:07:12 -0700217 if (err == NO_ERROR) {
Dan Stozad3182402014-11-17 12:03:59 -0800218 width = static_cast<int>(inWidth);
219 height = static_cast<int>(inHeight);
220 format = inFormat;
Craig Donner6ebc46a2016-10-21 15:23:44 -0700221 layerCount = inLayerCount;
Craig Donnere96a3252017-02-02 12:13:34 -0800222 usage = static_cast<int>(inProducerUsage | inConsumerUsage);
Dan Stozad3182402014-11-17 12:03:59 -0800223 stride = static_cast<int>(outStride);
Mathias Agopian3330b202009-10-05 17:07:12 -0700224 }
225 return err;
226}
227
Dan Stozad3182402014-11-17 12:03:59 -0800228status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr)
Mathias Agopian3330b202009-10-05 17:07:12 -0700229{
230 const Rect lockBounds(width, height);
Dan Stozad3182402014-11-17 12:03:59 -0800231 status_t res = lock(inUsage, lockBounds, vaddr);
Mathias Agopian3330b202009-10-05 17:07:12 -0700232 return res;
233}
234
Dan Stozad3182402014-11-17 12:03:59 -0800235status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr)
Mathias Agopian3330b202009-10-05 17:07:12 -0700236{
Dan Stozad3182402014-11-17 12:03:59 -0800237 if (rect.left < 0 || rect.right > width ||
238 rect.top < 0 || rect.bottom > height) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000239 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
Dan Stoza01049c82014-11-11 10:32:31 -0800240 rect.left, rect.top, rect.right, rect.bottom,
Dan Stozad3182402014-11-17 12:03:59 -0800241 width, height);
Mathias Agopian3330b202009-10-05 17:07:12 -0700242 return BAD_VALUE;
243 }
Dan Stozad3182402014-11-17 12:03:59 -0800244 status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr);
Mathias Agopian3330b202009-10-05 17:07:12 -0700245 return res;
246}
247
Dan Stozad3182402014-11-17 12:03:59 -0800248status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, android_ycbcr* ycbcr)
Eino-Ville Talvalac43946b2013-05-04 18:07:43 -0700249{
250 const Rect lockBounds(width, height);
Dan Stozad3182402014-11-17 12:03:59 -0800251 status_t res = lockYCbCr(inUsage, lockBounds, ycbcr);
Eino-Ville Talvalac43946b2013-05-04 18:07:43 -0700252 return res;
253}
254
Dan Stozad3182402014-11-17 12:03:59 -0800255status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, const Rect& rect,
256 android_ycbcr* ycbcr)
Eino-Ville Talvalac43946b2013-05-04 18:07:43 -0700257{
Dan Stozad3182402014-11-17 12:03:59 -0800258 if (rect.left < 0 || rect.right > width ||
259 rect.top < 0 || rect.bottom > height) {
Eino-Ville Talvalac43946b2013-05-04 18:07:43 -0700260 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
261 rect.left, rect.top, rect.right, rect.bottom,
Dan Stozad3182402014-11-17 12:03:59 -0800262 width, height);
Eino-Ville Talvalac43946b2013-05-04 18:07:43 -0700263 return BAD_VALUE;
264 }
Dan Stozad3182402014-11-17 12:03:59 -0800265 status_t res = getBufferMapper().lockYCbCr(handle, inUsage, rect, ycbcr);
Eino-Ville Talvalac43946b2013-05-04 18:07:43 -0700266 return res;
267}
268
Mathias Agopian3330b202009-10-05 17:07:12 -0700269status_t GraphicBuffer::unlock()
270{
271 status_t res = getBufferMapper().unlock(handle);
272 return res;
273}
274
Dan Stozad3182402014-11-17 12:03:59 -0800275status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd)
Francis Hart8f396012014-04-01 15:30:53 +0300276{
277 const Rect lockBounds(width, height);
Dan Stozad3182402014-11-17 12:03:59 -0800278 status_t res = lockAsync(inUsage, lockBounds, vaddr, fenceFd);
Francis Hart8f396012014-04-01 15:30:53 +0300279 return res;
280}
281
Dan Stozad3182402014-11-17 12:03:59 -0800282status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect,
283 void** vaddr, int fenceFd)
Francis Hart8f396012014-04-01 15:30:53 +0300284{
Craig Donnere96a3252017-02-02 12:13:34 -0800285 return lockAsync(inUsage, inUsage, rect, vaddr, fenceFd);
286}
287
288status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage,
289 uint64_t inConsumerUsage, const Rect& rect, void** vaddr, int fenceFd)
290{
Dan Stozad3182402014-11-17 12:03:59 -0800291 if (rect.left < 0 || rect.right > width ||
292 rect.top < 0 || rect.bottom > height) {
Francis Hart8f396012014-04-01 15:30:53 +0300293 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
294 rect.left, rect.top, rect.right, rect.bottom,
Dan Stozad3182402014-11-17 12:03:59 -0800295 width, height);
Francis Hart8f396012014-04-01 15:30:53 +0300296 return BAD_VALUE;
297 }
Craig Donnere96a3252017-02-02 12:13:34 -0800298 status_t res = getBufferMapper().lockAsync(handle, inProducerUsage,
299 inConsumerUsage, rect, vaddr, fenceFd);
Francis Hart8f396012014-04-01 15:30:53 +0300300 return res;
301}
302
Dan Stozad3182402014-11-17 12:03:59 -0800303status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, android_ycbcr* ycbcr,
304 int fenceFd)
Francis Hart8f396012014-04-01 15:30:53 +0300305{
306 const Rect lockBounds(width, height);
Dan Stozad3182402014-11-17 12:03:59 -0800307 status_t res = lockAsyncYCbCr(inUsage, lockBounds, ycbcr, fenceFd);
Francis Hart8f396012014-04-01 15:30:53 +0300308 return res;
309}
310
Dan Stozad3182402014-11-17 12:03:59 -0800311status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, const Rect& rect,
312 android_ycbcr* ycbcr, int fenceFd)
Francis Hart8f396012014-04-01 15:30:53 +0300313{
Dan Stozad3182402014-11-17 12:03:59 -0800314 if (rect.left < 0 || rect.right > width ||
315 rect.top < 0 || rect.bottom > height) {
Francis Hart8f396012014-04-01 15:30:53 +0300316 ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
317 rect.left, rect.top, rect.right, rect.bottom,
Dan Stozad3182402014-11-17 12:03:59 -0800318 width, height);
Francis Hart8f396012014-04-01 15:30:53 +0300319 return BAD_VALUE;
320 }
Dan Stozad3182402014-11-17 12:03:59 -0800321 status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect,
322 ycbcr, fenceFd);
Francis Hart8f396012014-04-01 15:30:53 +0300323 return res;
324}
325
326status_t GraphicBuffer::unlockAsync(int *fenceFd)
327{
328 status_t res = getBufferMapper().unlockAsync(handle, fenceFd);
329 return res;
330}
331
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800332size_t GraphicBuffer::getFlattenedSize() const {
Craig Donner6ebc46a2016-10-21 15:23:44 -0700333 return static_cast<size_t>(12 + (handle ? handle->numInts : 0)) * sizeof(int);
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800334}
Mathias Agopian3330b202009-10-05 17:07:12 -0700335
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800336size_t GraphicBuffer::getFdCount() const {
Dan Stozad3182402014-11-17 12:03:59 -0800337 return static_cast<size_t>(handle ? handle->numFds : 0);
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800338}
339
Mathias Agopiane1424282013-07-29 21:24:40 -0700340status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800341 size_t sizeNeeded = GraphicBuffer::getFlattenedSize();
342 if (size < sizeNeeded) return NO_MEMORY;
Mathias Agopian3330b202009-10-05 17:07:12 -0700343
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800344 size_t fdCountNeeded = GraphicBuffer::getFdCount();
345 if (count < fdCountNeeded) return NO_MEMORY;
Mathias Agopian3330b202009-10-05 17:07:12 -0700346
Dan Stozab1363d32014-03-28 15:10:52 -0700347 int32_t* buf = static_cast<int32_t*>(buffer);
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800348 buf[0] = 'GBFR';
349 buf[1] = width;
350 buf[2] = height;
351 buf[3] = stride;
352 buf[4] = format;
Craig Donner6ebc46a2016-10-21 15:23:44 -0700353 buf[5] = static_cast<int32_t>(layerCount);
354 buf[6] = usage;
355 buf[7] = static_cast<int32_t>(mId >> 32);
356 buf[8] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
357 buf[9] = static_cast<int32_t>(mGenerationNumber);
Dan Stoza812ed062015-06-02 15:45:22 -0700358 buf[10] = 0;
Craig Donner6ebc46a2016-10-21 15:23:44 -0700359 buf[11] = 0;
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800360
361 if (handle) {
Craig Donner6ebc46a2016-10-21 15:23:44 -0700362 buf[10] = handle->numFds;
363 buf[11] = handle->numInts;
Dan Stozad3182402014-11-17 12:03:59 -0800364 memcpy(fds, handle->data,
365 static_cast<size_t>(handle->numFds) * sizeof(int));
Craig Donner6ebc46a2016-10-21 15:23:44 -0700366 memcpy(&buf[12], handle->data + handle->numFds,
Dan Stozad3182402014-11-17 12:03:59 -0800367 static_cast<size_t>(handle->numInts) * sizeof(int));
Mathias Agopian3330b202009-10-05 17:07:12 -0700368 }
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800369
Dan Stozaeea6d682015-04-20 12:07:13 -0700370 buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded);
Mathias Agopiane1424282013-07-29 21:24:40 -0700371 size -= sizeNeeded;
Andy McFaddenbc96e472014-03-17 16:48:23 -0700372 if (handle) {
373 fds += handle->numFds;
Dan Stozad3182402014-11-17 12:03:59 -0800374 count -= static_cast<size_t>(handle->numFds);
Andy McFaddenbc96e472014-03-17 16:48:23 -0700375 }
Mathias Agopiane1424282013-07-29 21:24:40 -0700376
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800377 return NO_ERROR;
378}
379
Mathias Agopiane1424282013-07-29 21:24:40 -0700380status_t GraphicBuffer::unflatten(
381 void const*& buffer, size_t& size, int const*& fds, size_t& count) {
Craig Donner6ebc46a2016-10-21 15:23:44 -0700382 if (size < 12 * sizeof(int)) return NO_MEMORY;
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800383
384 int const* buf = static_cast<int const*>(buffer);
385 if (buf[0] != 'GBFR') return BAD_TYPE;
386
Craig Donner6ebc46a2016-10-21 15:23:44 -0700387 const size_t numFds = static_cast<size_t>(buf[10]);
388 const size_t numInts = static_cast<size_t>(buf[11]);
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800389
Michael Lentinec168b8a2015-02-18 10:14:18 -0800390 // Limit the maxNumber to be relatively small. The number of fds or ints
391 // should not come close to this number, and the number itself was simply
392 // chosen to be high enough to not cause issues and low enough to prevent
393 // overflow problems.
394 const size_t maxNumber = 4096;
Craig Donner6ebc46a2016-10-21 15:23:44 -0700395 if (numFds >= maxNumber || numInts >= (maxNumber - 12)) {
396 width = height = stride = format = layerCount = usage = 0;
Michael Lentine38803262014-10-31 15:25:03 -0700397 handle = NULL;
Dan Stoza01049c82014-11-11 10:32:31 -0800398 ALOGE("unflatten: numFds or numInts is too large: %zd, %zd",
Michael Lentine38803262014-10-31 15:25:03 -0700399 numFds, numInts);
400 return BAD_VALUE;
401 }
402
Craig Donner6ebc46a2016-10-21 15:23:44 -0700403 const size_t sizeNeeded = (12 + numInts) * sizeof(int);
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800404 if (size < sizeNeeded) return NO_MEMORY;
405
Michael Lentine38803262014-10-31 15:25:03 -0700406 size_t fdCountNeeded = numFds;
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800407 if (count < fdCountNeeded) return NO_MEMORY;
408
409 if (handle) {
410 // free previous handle if any
411 free_handle();
412 }
413
414 if (numFds || numInts) {
415 width = buf[1];
416 height = buf[2];
417 stride = buf[3];
418 format = buf[4];
Craig Donner6ebc46a2016-10-21 15:23:44 -0700419 layerCount = static_cast<uintptr_t>(buf[5]);
420 usage = buf[6];
Dan Stozad3182402014-11-17 12:03:59 -0800421 native_handle* h = native_handle_create(
422 static_cast<int>(numFds), static_cast<int>(numInts));
Michael Lentine38803262014-10-31 15:25:03 -0700423 if (!h) {
Craig Donner6ebc46a2016-10-21 15:23:44 -0700424 width = height = stride = format = layerCount = usage = 0;
Michael Lentine38803262014-10-31 15:25:03 -0700425 handle = NULL;
426 ALOGE("unflatten: native_handle_create failed");
427 return NO_MEMORY;
428 }
Dan Stozad3182402014-11-17 12:03:59 -0800429 memcpy(h->data, fds, numFds * sizeof(int));
Craig Donner6ebc46a2016-10-21 15:23:44 -0700430 memcpy(h->data + numFds, &buf[12], numInts * sizeof(int));
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800431 handle = h;
432 } else {
Craig Donner6ebc46a2016-10-21 15:23:44 -0700433 width = height = stride = format = layerCount = usage = 0;
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800434 handle = NULL;
435 }
436
Craig Donner6ebc46a2016-10-21 15:23:44 -0700437 mId = static_cast<uint64_t>(buf[7]) << 32;
438 mId |= static_cast<uint32_t>(buf[8]);
Dan Stozab1363d32014-03-28 15:10:52 -0700439
Craig Donner6ebc46a2016-10-21 15:23:44 -0700440 mGenerationNumber = static_cast<uint32_t>(buf[9]);
Dan Stoza812ed062015-06-02 15:45:22 -0700441
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800442 mOwner = ownHandle;
Jamie Gennis309d3bb2010-10-07 13:46:55 -0700443
444 if (handle != 0) {
Dan Stoza8deb4da2016-06-01 18:21:44 -0700445 status_t err = mBufferMapper.registerBuffer(this);
Jamie Gennisd69097f2012-08-30 13:28:23 -0700446 if (err != NO_ERROR) {
Craig Donner6ebc46a2016-10-21 15:23:44 -0700447 width = height = stride = format = layerCount = usage = 0;
Lingyun Zhu2aff7022012-11-20 19:24:35 +0800448 handle = NULL;
Jamie Gennisd69097f2012-08-30 13:28:23 -0700449 ALOGE("unflatten: registerBuffer failed: %s (%d)",
450 strerror(-err), err);
451 return err;
452 }
Jamie Gennis309d3bb2010-10-07 13:46:55 -0700453 }
454
Dan Stozaeea6d682015-04-20 12:07:13 -0700455 buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded);
Mathias Agopiane1424282013-07-29 21:24:40 -0700456 size -= sizeNeeded;
457 fds += numFds;
458 count -= numFds;
459
Mathias Agopian98e71dd2010-02-11 17:30:52 -0800460 return NO_ERROR;
Mathias Agopian3330b202009-10-05 17:07:12 -0700461}
462
Mathias Agopian3330b202009-10-05 17:07:12 -0700463// ---------------------------------------------------------------------------
464
465}; // namespace android