1 /*
2  * Copyright 2016 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 "Gralloc3"
18 
19 #include <hidl/ServiceManagement.h>
20 #include <hwbinder/IPCThreadState.h>
21 #include <ui/Gralloc3.h>
22 
23 #include <inttypes.h>
24 #include <log/log.h>
25 #pragma clang diagnostic push
26 #pragma clang diagnostic ignored "-Wzero-length-array"
27 #include <sync/sync.h>
28 #pragma clang diagnostic pop
29 
30 using android::hardware::graphics::allocator::V3_0::IAllocator;
31 using android::hardware::graphics::common::V1_2::BufferUsage;
32 using android::hardware::graphics::mapper::V3_0::BufferDescriptor;
33 using android::hardware::graphics::mapper::V3_0::Error;
34 using android::hardware::graphics::mapper::V3_0::IMapper;
35 using android::hardware::graphics::mapper::V3_0::YCbCrLayout;
36 
37 namespace android {
38 
39 namespace {
40 
41 static constexpr Error kTransactionError = Error::NO_RESOURCES;
42 
getValidUsageBits()43 uint64_t getValidUsageBits() {
44     static const uint64_t validUsageBits = []() -> uint64_t {
45         uint64_t bits = 0;
46         for (const auto bit :
47              hardware::hidl_enum_range<hardware::graphics::common::V1_2::BufferUsage>()) {
48             bits = bits | bit;
49         }
50         return bits;
51     }();
52     return validUsageBits;
53 }
54 
sGralloc3Rect(const Rect & rect)55 static inline IMapper::Rect sGralloc3Rect(const Rect& rect) {
56     IMapper::Rect outRect{};
57     outRect.left = rect.left;
58     outRect.top = rect.top;
59     outRect.width = rect.width();
60     outRect.height = rect.height();
61     return outRect;
62 }
sBufferDescriptorInfo(uint32_t width,uint32_t height,android::PixelFormat format,uint32_t layerCount,uint64_t usage,IMapper::BufferDescriptorInfo * outDescriptorInfo)63 static inline void sBufferDescriptorInfo(uint32_t width, uint32_t height,
64                                          android::PixelFormat format, uint32_t layerCount,
65                                          uint64_t usage,
66                                          IMapper::BufferDescriptorInfo* outDescriptorInfo) {
67     outDescriptorInfo->width = width;
68     outDescriptorInfo->height = height;
69     outDescriptorInfo->layerCount = layerCount;
70     outDescriptorInfo->format = static_cast<hardware::graphics::common::V1_2::PixelFormat>(format);
71     outDescriptorInfo->usage = usage;
72 }
73 
74 } // anonymous namespace
75 
preload()76 void Gralloc3Mapper::preload() {
77     android::hardware::preloadPassthroughService<IMapper>();
78 }
79 
Gralloc3Mapper()80 Gralloc3Mapper::Gralloc3Mapper() {
81     mMapper = IMapper::getService();
82     if (mMapper == nullptr) {
83         ALOGW("mapper 3.x is not supported");
84         return;
85     }
86     if (mMapper->isRemote()) {
87         LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
88     }
89 }
90 
isLoaded() const91 bool Gralloc3Mapper::isLoaded() const {
92     return mMapper != nullptr;
93 }
94 
validateBufferDescriptorInfo(IMapper::BufferDescriptorInfo * descriptorInfo) const95 status_t Gralloc3Mapper::validateBufferDescriptorInfo(
96         IMapper::BufferDescriptorInfo* descriptorInfo) const {
97     uint64_t validUsageBits = getValidUsageBits();
98 
99     if (descriptorInfo->usage & ~validUsageBits) {
100         ALOGE("buffer descriptor contains invalid usage bits 0x%" PRIx64,
101               descriptorInfo->usage & ~validUsageBits);
102         return BAD_VALUE;
103     }
104 
105     // Gralloc3 implementations never understand non-BLOB with GPU_DATA_BUFFER
106     // and do not reliably reject it.
107     if (descriptorInfo->usage & BufferUsage::GPU_DATA_BUFFER &&
108         descriptorInfo->format != hardware::graphics::common::V1_2::PixelFormat::BLOB) {
109         ALOGE("gralloc3 does not support non-BLOB pixel formats with GPU_DATA_BUFFER usage");
110         return BAD_VALUE;
111     }
112 
113     return NO_ERROR;
114 }
115 
createDescriptor(void * bufferDescriptorInfo,void * outBufferDescriptor) const116 status_t Gralloc3Mapper::createDescriptor(void* bufferDescriptorInfo,
117                                           void* outBufferDescriptor) const {
118     IMapper::BufferDescriptorInfo* descriptorInfo =
119             static_cast<IMapper::BufferDescriptorInfo*>(bufferDescriptorInfo);
120     BufferDescriptor* outDescriptor = static_cast<BufferDescriptor*>(outBufferDescriptor);
121 
122     status_t status = validateBufferDescriptorInfo(descriptorInfo);
123     if (status != NO_ERROR) {
124         return status;
125     }
126 
127     Error error;
128     auto hidl_cb = [&](const auto& tmpError, const auto& tmpDescriptor) {
129         error = tmpError;
130         if (error != Error::NONE) {
131             return;
132         }
133         *outDescriptor = tmpDescriptor;
134     };
135 
136     hardware::Return<void> ret = mMapper->createDescriptor(*descriptorInfo, hidl_cb);
137 
138     return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
139 }
140 
importBuffer(const native_handle_t * rawHandle,buffer_handle_t * outBufferHandle) const141 status_t Gralloc3Mapper::importBuffer(const native_handle_t* rawHandle,
142                                       buffer_handle_t* outBufferHandle) const {
143     Error error;
144     auto ret = mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
145         error = tmpError;
146         if (error != Error::NONE) {
147             return;
148         }
149         *outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
150     });
151 
152     return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
153 }
154 
freeBuffer(buffer_handle_t bufferHandle) const155 void Gralloc3Mapper::freeBuffer(buffer_handle_t bufferHandle) const {
156     auto buffer = const_cast<native_handle_t*>(bufferHandle);
157     auto ret = mMapper->freeBuffer(buffer);
158 
159     auto error = (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
160     ALOGE_IF(error != Error::NONE, "freeBuffer(%p) failed with %d", buffer, error);
161 }
162 
validateBufferSize(buffer_handle_t bufferHandle,uint32_t width,uint32_t height,android::PixelFormat format,uint32_t layerCount,uint64_t usage,uint32_t stride) const163 status_t Gralloc3Mapper::validateBufferSize(buffer_handle_t bufferHandle, uint32_t width,
164                                             uint32_t height, android::PixelFormat format,
165                                             uint32_t layerCount, uint64_t usage,
166                                             uint32_t stride) const {
167     IMapper::BufferDescriptorInfo descriptorInfo;
168     sBufferDescriptorInfo(width, height, format, layerCount, usage, &descriptorInfo);
169 
170     auto buffer = const_cast<native_handle_t*>(bufferHandle);
171     auto ret = mMapper->validateBufferSize(buffer, descriptorInfo, stride);
172 
173     return static_cast<status_t>((ret.isOk()) ? static_cast<Error>(ret) : kTransactionError);
174 }
175 
getTransportSize(buffer_handle_t bufferHandle,uint32_t * outNumFds,uint32_t * outNumInts) const176 void Gralloc3Mapper::getTransportSize(buffer_handle_t bufferHandle, uint32_t* outNumFds,
177                                       uint32_t* outNumInts) const {
178     *outNumFds = uint32_t(bufferHandle->numFds);
179     *outNumInts = uint32_t(bufferHandle->numInts);
180 
181     Error error;
182     auto buffer = const_cast<native_handle_t*>(bufferHandle);
183     auto ret = mMapper->getTransportSize(buffer,
184                                          [&](const auto& tmpError, const auto& tmpNumFds,
185                                              const auto& tmpNumInts) {
186                                              error = tmpError;
187                                              if (error != Error::NONE) {
188                                                  return;
189                                              }
190                                              *outNumFds = tmpNumFds;
191                                              *outNumInts = tmpNumInts;
192                                          });
193 
194     error = (ret.isOk()) ? error : kTransactionError;
195 
196     ALOGE_IF(error != Error::NONE, "getTransportSize(%p) failed with %d", buffer, error);
197 }
198 
lock(buffer_handle_t bufferHandle,uint64_t usage,const Rect & bounds,int acquireFence,void ** outData,int32_t * outBytesPerPixel,int32_t * outBytesPerStride) const199 status_t Gralloc3Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
200                               int acquireFence, void** outData, int32_t* outBytesPerPixel,
201                               int32_t* outBytesPerStride) const {
202     auto buffer = const_cast<native_handle_t*>(bufferHandle);
203 
204     IMapper::Rect accessRegion = sGralloc3Rect(bounds);
205 
206     // put acquireFence in a hidl_handle
207     hardware::hidl_handle acquireFenceHandle;
208     NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
209     if (acquireFence >= 0) {
210         auto h = native_handle_init(acquireFenceStorage, 1, 0);
211         h->data[0] = acquireFence;
212         acquireFenceHandle = h;
213     }
214 
215     Error error;
216     auto ret = mMapper->lock(buffer, usage, accessRegion, acquireFenceHandle,
217                              [&](const auto& tmpError, const auto& tmpData,
218                                  const auto& tmpBytesPerPixel, const auto& tmpBytesPerStride) {
219                                  error = tmpError;
220                                  if (error != Error::NONE) {
221                                      return;
222                                  }
223                                  *outData = tmpData;
224                                  if (outBytesPerPixel) {
225                                      *outBytesPerPixel = tmpBytesPerPixel;
226                                  }
227                                  if (outBytesPerStride) {
228                                      *outBytesPerStride = tmpBytesPerStride;
229                                  }
230                              });
231 
232     // we own acquireFence even on errors
233     if (acquireFence >= 0) {
234         close(acquireFence);
235     }
236 
237     error = (ret.isOk()) ? error : kTransactionError;
238 
239     ALOGW_IF(error != Error::NONE, "lock(%p, ...) failed: %d", bufferHandle, error);
240 
241     return static_cast<status_t>(error);
242 }
243 
lock(buffer_handle_t bufferHandle,uint64_t usage,const Rect & bounds,int acquireFence,android_ycbcr * ycbcr) const244 status_t Gralloc3Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
245                               int acquireFence, android_ycbcr* ycbcr) const {
246     auto buffer = const_cast<native_handle_t*>(bufferHandle);
247 
248     IMapper::Rect accessRegion = sGralloc3Rect(bounds);
249 
250     // put acquireFence in a hidl_handle
251     hardware::hidl_handle acquireFenceHandle;
252     NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
253     if (acquireFence >= 0) {
254         auto h = native_handle_init(acquireFenceStorage, 1, 0);
255         h->data[0] = acquireFence;
256         acquireFenceHandle = h;
257     }
258 
259     YCbCrLayout layout;
260     Error error;
261     auto ret = mMapper->lockYCbCr(buffer, usage, accessRegion, acquireFenceHandle,
262                                   [&](const auto& tmpError, const auto& tmpLayout) {
263                                       error = tmpError;
264                                       if (error != Error::NONE) {
265                                           return;
266                                       }
267 
268                                       layout = tmpLayout;
269                                   });
270 
271     if (error == Error::NONE) {
272         ycbcr->y = layout.y;
273         ycbcr->cb = layout.cb;
274         ycbcr->cr = layout.cr;
275         ycbcr->ystride = static_cast<size_t>(layout.yStride);
276         ycbcr->cstride = static_cast<size_t>(layout.cStride);
277         ycbcr->chroma_step = static_cast<size_t>(layout.chromaStep);
278     }
279 
280     // we own acquireFence even on errors
281     if (acquireFence >= 0) {
282         close(acquireFence);
283     }
284 
285     return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
286 }
287 
unlock(buffer_handle_t bufferHandle) const288 int Gralloc3Mapper::unlock(buffer_handle_t bufferHandle) const {
289     auto buffer = const_cast<native_handle_t*>(bufferHandle);
290 
291     int releaseFence = -1;
292     Error error;
293     auto ret = mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
294         error = tmpError;
295         if (error != Error::NONE) {
296             return;
297         }
298 
299         auto fenceHandle = tmpReleaseFence.getNativeHandle();
300         if (fenceHandle && fenceHandle->numFds == 1) {
301             int fd = dup(fenceHandle->data[0]);
302             if (fd >= 0) {
303                 releaseFence = fd;
304             } else {
305                 ALOGD("failed to dup unlock release fence");
306                 sync_wait(fenceHandle->data[0], -1);
307             }
308         }
309     });
310 
311     if (!ret.isOk()) {
312         error = kTransactionError;
313     }
314 
315     if (error != Error::NONE) {
316         ALOGE("unlock(%p) failed with %d", buffer, error);
317     }
318 
319     return releaseFence;
320 }
321 
isSupported(uint32_t width,uint32_t height,android::PixelFormat format,uint32_t layerCount,uint64_t usage,bool * outSupported) const322 status_t Gralloc3Mapper::isSupported(uint32_t width, uint32_t height, android::PixelFormat format,
323                                      uint32_t layerCount, uint64_t usage,
324                                      bool* outSupported) const {
325     IMapper::BufferDescriptorInfo descriptorInfo;
326     sBufferDescriptorInfo(width, height, format, layerCount, usage, &descriptorInfo);
327 
328     Error error;
329     auto ret = mMapper->isSupported(descriptorInfo,
330                                     [&](const auto& tmpError, const auto& tmpSupported) {
331                                         error = tmpError;
332                                         if (error != Error::NONE) {
333                                             return;
334                                         }
335                                         if (outSupported) {
336                                             *outSupported = tmpSupported;
337                                         }
338                                     });
339 
340     if (!ret.isOk()) {
341         error = kTransactionError;
342     }
343 
344     if (error != Error::NONE) {
345         ALOGE("isSupported(%u, %u, %d, %u, ...) failed with %d", width, height, format, layerCount,
346               error);
347     }
348 
349     return static_cast<status_t>(error);
350 }
351 
Gralloc3Allocator(const Gralloc3Mapper & mapper)352 Gralloc3Allocator::Gralloc3Allocator(const Gralloc3Mapper& mapper) : mMapper(mapper) {
353     mAllocator = IAllocator::getService();
354     if (mAllocator == nullptr) {
355         ALOGW("allocator 3.x is not supported");
356         return;
357     }
358 }
359 
isLoaded() const360 bool Gralloc3Allocator::isLoaded() const {
361     return mAllocator != nullptr;
362 }
363 
dumpDebugInfo(bool) const364 std::string Gralloc3Allocator::dumpDebugInfo(bool /*less*/) const {
365     std::string debugInfo;
366 
367     mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
368 
369     return debugInfo;
370 }
371 
allocate(std::string,uint32_t width,uint32_t height,android::PixelFormat format,uint32_t layerCount,uint64_t usage,uint32_t * outStride,buffer_handle_t * outBufferHandles,bool importBuffers) const372 status_t Gralloc3Allocator::allocate(std::string /*requestorName*/, uint32_t width, uint32_t height,
373                                      android::PixelFormat format, uint32_t layerCount,
374                                      uint64_t usage, uint32_t* outStride,
375                                      buffer_handle_t* outBufferHandles, bool importBuffers) const {
376     IMapper::BufferDescriptorInfo descriptorInfo;
377     sBufferDescriptorInfo(width, height, format, layerCount, usage, &descriptorInfo);
378 
379     BufferDescriptor descriptor;
380     status_t error = mMapper.createDescriptor(static_cast<void*>(&descriptorInfo),
381                                               static_cast<void*>(&descriptor));
382     if (error != NO_ERROR) {
383         return error;
384     }
385 
386     constexpr auto bufferCount = 1;
387 
388     auto ret = mAllocator->allocate(descriptor, bufferCount,
389                                     [&](const auto& tmpError, const auto& tmpStride,
390                                         const auto& tmpBuffers) {
391                                         error = static_cast<status_t>(tmpError);
392                                         if (tmpError != Error::NONE) {
393                                             return;
394                                         }
395 
396                                         if (importBuffers) {
397                                             for (uint32_t i = 0; i < bufferCount; i++) {
398                                                 error = mMapper.importBuffer(tmpBuffers[i],
399                                                                              &outBufferHandles[i]);
400                                                 if (error != NO_ERROR) {
401                                                     for (uint32_t j = 0; j < i; j++) {
402                                                         mMapper.freeBuffer(outBufferHandles[j]);
403                                                         outBufferHandles[j] = nullptr;
404                                                     }
405                                                     return;
406                                                 }
407                                             }
408                                         } else {
409                                             for (uint32_t i = 0; i < bufferCount; i++) {
410                                                 outBufferHandles[i] = native_handle_clone(
411                                                         tmpBuffers[i].getNativeHandle());
412                                                 if (!outBufferHandles[i]) {
413                                                     for (uint32_t j = 0; j < i; j++) {
414                                                         auto buffer = const_cast<native_handle_t*>(
415                                                                 outBufferHandles[j]);
416                                                         native_handle_close(buffer);
417                                                         native_handle_delete(buffer);
418                                                         outBufferHandles[j] = nullptr;
419                                                     }
420                                                 }
421                                             }
422                                         }
423                                         *outStride = tmpStride;
424                                     });
425 
426     // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
427     hardware::IPCThreadState::self()->flushCommands();
428 
429     return (ret.isOk()) ? error : static_cast<status_t>(kTransactionError);
430 }
431 
432 } // namespace android
433