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