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 return NO_ERROR;
105 }
106
createDescriptor(void * bufferDescriptorInfo,void * outBufferDescriptor) const107 status_t Gralloc3Mapper::createDescriptor(void* bufferDescriptorInfo,
108 void* outBufferDescriptor) const {
109 IMapper::BufferDescriptorInfo* descriptorInfo =
110 static_cast<IMapper::BufferDescriptorInfo*>(bufferDescriptorInfo);
111 BufferDescriptor* outDescriptor = static_cast<BufferDescriptor*>(outBufferDescriptor);
112
113 status_t status = validateBufferDescriptorInfo(descriptorInfo);
114 if (status != NO_ERROR) {
115 return status;
116 }
117
118 Error error;
119 auto hidl_cb = [&](const auto& tmpError, const auto& tmpDescriptor) {
120 error = tmpError;
121 if (error != Error::NONE) {
122 return;
123 }
124 *outDescriptor = tmpDescriptor;
125 };
126
127 hardware::Return<void> ret = mMapper->createDescriptor(*descriptorInfo, hidl_cb);
128
129 return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
130 }
131
importBuffer(const hardware::hidl_handle & rawHandle,buffer_handle_t * outBufferHandle) const132 status_t Gralloc3Mapper::importBuffer(const hardware::hidl_handle& rawHandle,
133 buffer_handle_t* outBufferHandle) const {
134 Error error;
135 auto ret = mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
136 error = tmpError;
137 if (error != Error::NONE) {
138 return;
139 }
140 *outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
141 });
142
143 return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
144 }
145
freeBuffer(buffer_handle_t bufferHandle) const146 void Gralloc3Mapper::freeBuffer(buffer_handle_t bufferHandle) const {
147 auto buffer = const_cast<native_handle_t*>(bufferHandle);
148 auto ret = mMapper->freeBuffer(buffer);
149
150 auto error = (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
151 ALOGE_IF(error != Error::NONE, "freeBuffer(%p) failed with %d", buffer, error);
152 }
153
validateBufferSize(buffer_handle_t bufferHandle,uint32_t width,uint32_t height,android::PixelFormat format,uint32_t layerCount,uint64_t usage,uint32_t stride) const154 status_t Gralloc3Mapper::validateBufferSize(buffer_handle_t bufferHandle, uint32_t width,
155 uint32_t height, android::PixelFormat format,
156 uint32_t layerCount, uint64_t usage,
157 uint32_t stride) const {
158 IMapper::BufferDescriptorInfo descriptorInfo;
159 sBufferDescriptorInfo(width, height, format, layerCount, usage, &descriptorInfo);
160
161 auto buffer = const_cast<native_handle_t*>(bufferHandle);
162 auto ret = mMapper->validateBufferSize(buffer, descriptorInfo, stride);
163
164 return static_cast<status_t>((ret.isOk()) ? static_cast<Error>(ret) : kTransactionError);
165 }
166
getTransportSize(buffer_handle_t bufferHandle,uint32_t * outNumFds,uint32_t * outNumInts) const167 void Gralloc3Mapper::getTransportSize(buffer_handle_t bufferHandle, uint32_t* outNumFds,
168 uint32_t* outNumInts) const {
169 *outNumFds = uint32_t(bufferHandle->numFds);
170 *outNumInts = uint32_t(bufferHandle->numInts);
171
172 Error error;
173 auto buffer = const_cast<native_handle_t*>(bufferHandle);
174 auto ret = mMapper->getTransportSize(buffer,
175 [&](const auto& tmpError, const auto& tmpNumFds,
176 const auto& tmpNumInts) {
177 error = tmpError;
178 if (error != Error::NONE) {
179 return;
180 }
181 *outNumFds = tmpNumFds;
182 *outNumInts = tmpNumInts;
183 });
184
185 error = (ret.isOk()) ? error : kTransactionError;
186
187 ALOGE_IF(error != Error::NONE, "getTransportSize(%p) failed with %d", buffer, error);
188 }
189
lock(buffer_handle_t bufferHandle,uint64_t usage,const Rect & bounds,int acquireFence,void ** outData,int32_t * outBytesPerPixel,int32_t * outBytesPerStride) const190 status_t Gralloc3Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
191 int acquireFence, void** outData, int32_t* outBytesPerPixel,
192 int32_t* outBytesPerStride) const {
193 auto buffer = const_cast<native_handle_t*>(bufferHandle);
194
195 IMapper::Rect accessRegion = sGralloc3Rect(bounds);
196
197 // put acquireFence in a hidl_handle
198 hardware::hidl_handle acquireFenceHandle;
199 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
200 if (acquireFence >= 0) {
201 auto h = native_handle_init(acquireFenceStorage, 1, 0);
202 h->data[0] = acquireFence;
203 acquireFenceHandle = h;
204 }
205
206 Error error;
207 auto ret = mMapper->lock(buffer, usage, accessRegion, acquireFenceHandle,
208 [&](const auto& tmpError, const auto& tmpData,
209 const auto& tmpBytesPerPixel, const auto& tmpBytesPerStride) {
210 error = tmpError;
211 if (error != Error::NONE) {
212 return;
213 }
214 *outData = tmpData;
215 if (outBytesPerPixel) {
216 *outBytesPerPixel = tmpBytesPerPixel;
217 }
218 if (outBytesPerStride) {
219 *outBytesPerStride = tmpBytesPerStride;
220 }
221 });
222
223 // we own acquireFence even on errors
224 if (acquireFence >= 0) {
225 close(acquireFence);
226 }
227
228 error = (ret.isOk()) ? error : kTransactionError;
229
230 ALOGW_IF(error != Error::NONE, "lock(%p, ...) failed: %d", bufferHandle, error);
231
232 return static_cast<status_t>(error);
233 }
234
lock(buffer_handle_t bufferHandle,uint64_t usage,const Rect & bounds,int acquireFence,android_ycbcr * ycbcr) const235 status_t Gralloc3Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
236 int acquireFence, android_ycbcr* ycbcr) const {
237 auto buffer = const_cast<native_handle_t*>(bufferHandle);
238
239 IMapper::Rect accessRegion = sGralloc3Rect(bounds);
240
241 // put acquireFence in a hidl_handle
242 hardware::hidl_handle acquireFenceHandle;
243 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
244 if (acquireFence >= 0) {
245 auto h = native_handle_init(acquireFenceStorage, 1, 0);
246 h->data[0] = acquireFence;
247 acquireFenceHandle = h;
248 }
249
250 YCbCrLayout layout;
251 Error error;
252 auto ret = mMapper->lockYCbCr(buffer, usage, accessRegion, acquireFenceHandle,
253 [&](const auto& tmpError, const auto& tmpLayout) {
254 error = tmpError;
255 if (error != Error::NONE) {
256 return;
257 }
258
259 layout = tmpLayout;
260 });
261
262 if (error == Error::NONE) {
263 ycbcr->y = layout.y;
264 ycbcr->cb = layout.cb;
265 ycbcr->cr = layout.cr;
266 ycbcr->ystride = static_cast<size_t>(layout.yStride);
267 ycbcr->cstride = static_cast<size_t>(layout.cStride);
268 ycbcr->chroma_step = static_cast<size_t>(layout.chromaStep);
269 }
270
271 // we own acquireFence even on errors
272 if (acquireFence >= 0) {
273 close(acquireFence);
274 }
275
276 return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
277 }
278
unlock(buffer_handle_t bufferHandle) const279 int Gralloc3Mapper::unlock(buffer_handle_t bufferHandle) const {
280 auto buffer = const_cast<native_handle_t*>(bufferHandle);
281
282 int releaseFence = -1;
283 Error error;
284 auto ret = mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
285 error = tmpError;
286 if (error != Error::NONE) {
287 return;
288 }
289
290 auto fenceHandle = tmpReleaseFence.getNativeHandle();
291 if (fenceHandle && fenceHandle->numFds == 1) {
292 int fd = dup(fenceHandle->data[0]);
293 if (fd >= 0) {
294 releaseFence = fd;
295 } else {
296 ALOGD("failed to dup unlock release fence");
297 sync_wait(fenceHandle->data[0], -1);
298 }
299 }
300 });
301
302 if (!ret.isOk()) {
303 error = kTransactionError;
304 }
305
306 if (error != Error::NONE) {
307 ALOGE("unlock(%p) failed with %d", buffer, error);
308 }
309
310 return releaseFence;
311 }
312
isSupported(uint32_t width,uint32_t height,android::PixelFormat format,uint32_t layerCount,uint64_t usage,bool * outSupported) const313 status_t Gralloc3Mapper::isSupported(uint32_t width, uint32_t height, android::PixelFormat format,
314 uint32_t layerCount, uint64_t usage,
315 bool* outSupported) const {
316 IMapper::BufferDescriptorInfo descriptorInfo;
317 sBufferDescriptorInfo(width, height, format, layerCount, usage, &descriptorInfo);
318
319 Error error;
320 auto ret = mMapper->isSupported(descriptorInfo,
321 [&](const auto& tmpError, const auto& tmpSupported) {
322 error = tmpError;
323 if (error != Error::NONE) {
324 return;
325 }
326 if (outSupported) {
327 *outSupported = tmpSupported;
328 }
329 });
330
331 if (!ret.isOk()) {
332 error = kTransactionError;
333 }
334
335 if (error != Error::NONE) {
336 ALOGE("isSupported(%u, %u, %d, %u, ...) failed with %d", width, height, format, layerCount,
337 error);
338 }
339
340 return static_cast<status_t>(error);
341 }
342
Gralloc3Allocator(const Gralloc3Mapper & mapper)343 Gralloc3Allocator::Gralloc3Allocator(const Gralloc3Mapper& mapper) : mMapper(mapper) {
344 mAllocator = IAllocator::getService();
345 if (mAllocator == nullptr) {
346 ALOGW("allocator 3.x is not supported");
347 return;
348 }
349 }
350
isLoaded() const351 bool Gralloc3Allocator::isLoaded() const {
352 return mAllocator != nullptr;
353 }
354
dumpDebugInfo(bool) const355 std::string Gralloc3Allocator::dumpDebugInfo(bool /*less*/) const {
356 std::string debugInfo;
357
358 mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
359
360 return debugInfo;
361 }
362
allocate(std::string,uint32_t width,uint32_t height,android::PixelFormat format,uint32_t layerCount,uint64_t usage,uint32_t bufferCount,uint32_t * outStride,buffer_handle_t * outBufferHandles,bool importBuffers) const363 status_t Gralloc3Allocator::allocate(std::string /*requestorName*/, uint32_t width, uint32_t height,
364 android::PixelFormat format, uint32_t layerCount,
365 uint64_t usage, uint32_t bufferCount, uint32_t* outStride,
366 buffer_handle_t* outBufferHandles, bool importBuffers) const {
367 IMapper::BufferDescriptorInfo descriptorInfo;
368 sBufferDescriptorInfo(width, height, format, layerCount, usage, &descriptorInfo);
369
370 BufferDescriptor descriptor;
371 status_t error = mMapper.createDescriptor(static_cast<void*>(&descriptorInfo),
372 static_cast<void*>(&descriptor));
373 if (error != NO_ERROR) {
374 return error;
375 }
376
377 auto ret = mAllocator->allocate(descriptor, bufferCount,
378 [&](const auto& tmpError, const auto& tmpStride,
379 const auto& tmpBuffers) {
380 error = static_cast<status_t>(tmpError);
381 if (tmpError != Error::NONE) {
382 return;
383 }
384
385 if (importBuffers) {
386 for (uint32_t i = 0; i < bufferCount; i++) {
387 error = mMapper.importBuffer(tmpBuffers[i],
388 &outBufferHandles[i]);
389 if (error != NO_ERROR) {
390 for (uint32_t j = 0; j < i; j++) {
391 mMapper.freeBuffer(outBufferHandles[j]);
392 outBufferHandles[j] = nullptr;
393 }
394 return;
395 }
396 }
397 } else {
398 for (uint32_t i = 0; i < bufferCount; i++) {
399 outBufferHandles[i] = native_handle_clone(
400 tmpBuffers[i].getNativeHandle());
401 if (!outBufferHandles[i]) {
402 for (uint32_t j = 0; j < i; j++) {
403 auto buffer = const_cast<native_handle_t*>(
404 outBufferHandles[j]);
405 native_handle_close(buffer);
406 native_handle_delete(buffer);
407 outBufferHandles[j] = nullptr;
408 }
409 }
410 }
411 }
412 *outStride = tmpStride;
413 });
414
415 // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
416 hardware::IPCThreadState::self()->flushCommands();
417
418 return (ret.isOk()) ? error : static_cast<status_t>(kTransactionError);
419 }
420
421 } // namespace android
422