1 /*
2 * Copyright (C) 2022 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 "Gralloc5"
18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19
20 #include <ui/Gralloc5.h>
21
22 #include <aidl/android/hardware/graphics/allocator/AllocationError.h>
23 #include <aidlcommonsupport/NativeHandle.h>
24 #include <android/binder_manager.h>
25 #include <android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h>
26 #include <binder/IPCThreadState.h>
27 #include <dlfcn.h>
28 #include <ui/FatVector.h>
29 #include <vndksupport/linker.h>
30
31 using namespace aidl::android::hardware::graphics::allocator;
32 using namespace aidl::android::hardware::graphics::common;
33 using namespace ::android::hardware::graphics::mapper;
34
35 using ADataspace = aidl::android::hardware::graphics::common::Dataspace;
36 using APixelFormat = aidl::android::hardware::graphics::common::PixelFormat;
37
38 namespace android {
39
40 static const auto kIAllocatorServiceName = IAllocator::descriptor + std::string("/default");
41 static const auto kIAllocatorMinimumVersion = 2;
42 constexpr const char* kStandardMetadataName =
43 "android.hardware.graphics.common.StandardMetadataType";
44
45 // TODO(b/72323293, b/72703005): Remove these invalid bits from callers
46 static constexpr uint64_t kRemovedUsageBits = static_cast<uint64_t>((1 << 10) | (1 << 13));
47
48 typedef AIMapper_Error (*AIMapper_loadIMapperFn)(AIMapper *_Nullable *_Nonnull outImplementation);
49
50 struct Gralloc5 {
51 std::shared_ptr<IAllocator> allocator;
52 AIMapper *mapper = nullptr;
53 };
54
waitForAllocator()55 static std::shared_ptr<IAllocator> waitForAllocator() {
56 if (__builtin_available(android 31, *)) {
57 if (!AServiceManager_isDeclared(kIAllocatorServiceName.c_str())) {
58 return nullptr;
59 }
60 auto allocator = IAllocator::fromBinder(
61 ndk::SpAIBinder(AServiceManager_waitForService(kIAllocatorServiceName.c_str())));
62 if (!allocator) {
63 ALOGE("AIDL IAllocator declared but failed to get service");
64 return nullptr;
65 }
66
67 int32_t version = 0;
68 if (!allocator->getInterfaceVersion(&version).isOk()) {
69 ALOGE("Failed to query interface version");
70 return nullptr;
71 }
72 if (version < kIAllocatorMinimumVersion) {
73 return nullptr;
74 }
75 return allocator;
76 } else {
77 // TODO: LOG_ALWAYS_FATAL("libui is not backwards compatible");
78 return nullptr;
79 }
80 }
81
loadIMapperLibrary()82 static void *loadIMapperLibrary() {
83 static void *imapperLibrary = []() -> void * {
84 auto allocator = waitForAllocator();
85 std::string mapperSuffix;
86 auto status = allocator->getIMapperLibrarySuffix(&mapperSuffix);
87 if (!status.isOk()) {
88 ALOGE("Failed to get IMapper library suffix");
89 return nullptr;
90 }
91
92 void* so = nullptr;
93 if (__builtin_available(android __ANDROID_API_V__, *)) {
94 so = AServiceManager_openDeclaredPassthroughHal("mapper", mapperSuffix.c_str(),
95 RTLD_LOCAL | RTLD_NOW);
96 } else {
97 std::string lib_name = "mapper." + mapperSuffix + ".so";
98 so = android_load_sphal_library(lib_name.c_str(), RTLD_LOCAL | RTLD_NOW);
99 }
100 if (!so) {
101 ALOGE("Failed to load mapper.%s.so", mapperSuffix.c_str());
102 }
103 return so;
104 }();
105 return imapperLibrary;
106 }
107
getInstance()108 static const Gralloc5 &getInstance() {
109 static Gralloc5 instance = []() {
110 auto allocator = waitForAllocator();
111 if (!allocator) {
112 return Gralloc5{};
113 }
114 void *so = loadIMapperLibrary();
115 if (!so) {
116 return Gralloc5{};
117 }
118 auto loadIMapper = (AIMapper_loadIMapperFn)dlsym(so, "AIMapper_loadIMapper");
119 AIMapper *mapper = nullptr;
120 AIMapper_Error error = loadIMapper(&mapper);
121 if (error != AIMAPPER_ERROR_NONE) {
122 ALOGE("AIMapper_loadIMapper failed %d", error);
123 return Gralloc5{};
124 }
125 return Gralloc5{std::move(allocator), mapper};
126 }();
127 return instance;
128 }
129
130 template <StandardMetadataType T>
getStandardMetadata(AIMapper * mapper,buffer_handle_t bufferHandle)131 static auto getStandardMetadata(AIMapper *mapper, buffer_handle_t bufferHandle)
132 -> decltype(StandardMetadata<T>::value::decode(nullptr, 0)) {
133 using Value = typename StandardMetadata<T>::value;
134 // TODO: Tune for common-case better
135 FatVector<uint8_t, 128> buffer;
136 int32_t sizeRequired = mapper->v5.getStandardMetadata(bufferHandle, static_cast<int64_t>(T),
137 buffer.data(), buffer.size());
138 if (sizeRequired < 0) {
139 ALOGW_IF(-AIMAPPER_ERROR_UNSUPPORTED != sizeRequired,
140 "Unexpected error %d from valid getStandardMetadata call", -sizeRequired);
141 return std::nullopt;
142 }
143 if ((size_t)sizeRequired > buffer.size()) {
144 buffer.resize(sizeRequired);
145 sizeRequired = mapper->v5.getStandardMetadata(bufferHandle, static_cast<int64_t>(T),
146 buffer.data(), buffer.size());
147 }
148 if (sizeRequired < 0 || (size_t)sizeRequired > buffer.size()) {
149 ALOGW("getStandardMetadata failed, received %d with buffer size %zd", sizeRequired,
150 buffer.size());
151 // Generate a fail type
152 return std::nullopt;
153 }
154 return Value::decode(buffer.data(), sizeRequired);
155 }
156
157 template <StandardMetadataType T>
setStandardMetadata(AIMapper * mapper,buffer_handle_t bufferHandle,const typename StandardMetadata<T>::value_type & value)158 static AIMapper_Error setStandardMetadata(AIMapper *mapper, buffer_handle_t bufferHandle,
159 const typename StandardMetadata<T>::value_type &value) {
160 using Value = typename StandardMetadata<T>::value;
161 int32_t sizeRequired = Value::encode(value, nullptr, 0);
162 if (sizeRequired < 0) {
163 ALOGW("Failed to calculate required size");
164 return static_cast<AIMapper_Error>(-sizeRequired);
165 }
166 FatVector<uint8_t, 128> buffer;
167 buffer.resize(sizeRequired);
168 sizeRequired = Value::encode(value, buffer.data(), buffer.size());
169 if (sizeRequired < 0 || (size_t)sizeRequired > buffer.size()) {
170 ALOGW("Failed to encode with calculated size %d; buffer size %zd", sizeRequired,
171 buffer.size());
172 return static_cast<AIMapper_Error>(-sizeRequired);
173 }
174 return mapper->v5.setStandardMetadata(bufferHandle, static_cast<int64_t>(T), buffer.data(),
175 sizeRequired);
176 }
177
Gralloc5Allocator(const Gralloc5Mapper & mapper)178 Gralloc5Allocator::Gralloc5Allocator(const Gralloc5Mapper &mapper) : mMapper(mapper) {
179 mAllocator = getInstance().allocator;
180 }
181
isLoaded() const182 bool Gralloc5Allocator::isLoaded() const {
183 return mAllocator != nullptr;
184 }
185
getValidUsageBits()186 static uint64_t getValidUsageBits() {
187 static const uint64_t validUsageBits = []() -> uint64_t {
188 uint64_t bits = 0;
189 for (const auto bit : ndk::enum_range<BufferUsage>{}) {
190 bits |= static_cast<int64_t>(bit);
191 }
192 return bits;
193 }();
194 return validUsageBits | kRemovedUsageBits;
195 }
196
makeDescriptor(std::string requestorName,uint32_t width,uint32_t height,PixelFormat format,uint32_t layerCount,uint64_t usage)197 static std::optional<BufferDescriptorInfo> makeDescriptor(std::string requestorName, uint32_t width,
198 uint32_t height, PixelFormat format,
199 uint32_t layerCount, uint64_t usage) {
200 uint64_t validUsageBits = getValidUsageBits();
201 if (usage & ~validUsageBits) {
202 ALOGE("buffer descriptor contains invalid usage bits 0x%" PRIx64, usage & ~validUsageBits);
203 return std::nullopt;
204 }
205
206 BufferDescriptorInfo descriptorInfo{
207 .width = static_cast<int32_t>(width),
208 .height = static_cast<int32_t>(height),
209 .layerCount = static_cast<int32_t>(layerCount),
210 .format = static_cast<::aidl::android::hardware::graphics::common::PixelFormat>(format),
211 .usage = static_cast<BufferUsage>(usage),
212 };
213 auto nameLength = std::min(requestorName.length(), descriptorInfo.name.size() - 1);
214 memcpy(descriptorInfo.name.data(), requestorName.data(), nameLength);
215 requestorName.data()[nameLength] = 0;
216 return descriptorInfo;
217 }
218
dumpDebugInfo(bool less) const219 std::string Gralloc5Allocator::dumpDebugInfo(bool less) const {
220 return mMapper.dumpBuffers(less);
221 }
222
allocate(std::string requestorName,uint32_t width,uint32_t height,android::PixelFormat format,uint32_t layerCount,uint64_t usage,uint32_t * outStride,buffer_handle_t * outBufferHandles,bool importBuffers) const223 status_t Gralloc5Allocator::allocate(std::string requestorName, uint32_t width, uint32_t height,
224 android::PixelFormat format, uint32_t layerCount,
225 uint64_t usage, uint32_t* outStride,
226 buffer_handle_t* outBufferHandles, bool importBuffers) const {
227 auto result = allocate(GraphicBufferAllocator::AllocationRequest{
228 .importBuffer = importBuffers,
229 .width = width,
230 .height = height,
231 .format = format,
232 .layerCount = layerCount,
233 .usage = usage,
234 .requestorName = requestorName,
235 });
236
237 *outStride = result.stride;
238 outBufferHandles[0] = result.handle;
239 return result.status;
240 }
241
allocate(const GraphicBufferAllocator::AllocationRequest & request) const242 GraphicBufferAllocator::AllocationResult Gralloc5Allocator::allocate(
243 const GraphicBufferAllocator::AllocationRequest& request) const {
244 auto descriptorInfo = makeDescriptor(request.requestorName, request.width, request.height,
245 request.format, request.layerCount, request.usage);
246 if (!descriptorInfo) {
247 return GraphicBufferAllocator::AllocationResult{BAD_VALUE};
248 }
249
250 descriptorInfo->additionalOptions.reserve(request.extras.size());
251 for (const auto& option : request.extras) {
252 ExtendableType type;
253 type.name = option.name;
254 type.value = option.value;
255 descriptorInfo->additionalOptions.push_back(std::move(type));
256 }
257
258 AllocationResult result;
259 auto status = mAllocator->allocate2(*descriptorInfo, 1, &result);
260 if (!status.isOk()) {
261 auto error = status.getExceptionCode();
262 if (error == EX_SERVICE_SPECIFIC) {
263 switch (static_cast<AllocationError>(status.getServiceSpecificError())) {
264 case AllocationError::BAD_DESCRIPTOR:
265 error = BAD_VALUE;
266 break;
267 case AllocationError::NO_RESOURCES:
268 error = NO_MEMORY;
269 break;
270 default:
271 error = UNKNOWN_ERROR;
272 break;
273 }
274 }
275 return GraphicBufferAllocator::AllocationResult{error};
276 }
277
278 GraphicBufferAllocator::AllocationResult ret{OK};
279 if (request.importBuffer) {
280 auto handle = makeFromAidl(result.buffers[0]);
281 auto error = mMapper.importBuffer(handle, &ret.handle);
282 native_handle_delete(handle);
283 if (error != NO_ERROR) {
284 return GraphicBufferAllocator::AllocationResult{error};
285 }
286 } else {
287 ret.handle = dupFromAidl(result.buffers[0]);
288 if (!ret.handle) {
289 return GraphicBufferAllocator::AllocationResult{NO_MEMORY};
290 }
291 }
292
293 ret.stride = result.stride;
294
295 // Release all the resources held by AllocationResult (specifically any remaining FDs)
296 result = {};
297 // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
298 // TODO: Re-enable this at some point if it's necessary. We can't do it now because libui
299 // is marked apex_available (b/214400477) and libbinder isn't (which of course is correct)
300 // IPCThreadState::self()->flushCommands();
301
302 return ret;
303 }
304
preload()305 void Gralloc5Mapper::preload() {
306 // TODO(b/261858155): Implement. We can't bounce off of IAllocator for this because zygote can't
307 // use binder. So when an alternate strategy of retrieving the library prefix is available,
308 // use that here.
309 }
310
Gralloc5Mapper()311 Gralloc5Mapper::Gralloc5Mapper() {
312 mMapper = getInstance().mapper;
313 }
314
isLoaded() const315 bool Gralloc5Mapper::isLoaded() const {
316 return mMapper != nullptr && mMapper->version >= AIMAPPER_VERSION_5;
317 }
318
isStandardMetadata(AIMapper_MetadataType metadataType)319 static bool isStandardMetadata(AIMapper_MetadataType metadataType) {
320 return strcmp(kStandardMetadataName, metadataType.name) == 0;
321 }
322
323 struct DumpBufferResult {
324 uint64_t bufferId;
325 std::string name;
326 uint64_t width;
327 uint64_t height;
328 uint64_t layerCount;
329 APixelFormat pixelFormatRequested;
330 uint32_t pixelFormatFourCC;
331 uint64_t pixelFormatModifier;
332 BufferUsage usage;
333 ADataspace dataspace;
334 uint64_t allocationSize;
335 uint64_t protectedContent;
336 ExtendableType compression;
337 ExtendableType interlaced;
338 ExtendableType chromaSiting;
339 std::vector<ui::PlaneLayout> planeLayouts;
340 };
341
342 #define DECODE_TO(name, output) \
343 case StandardMetadataType::name: \
344 output = StandardMetadata<StandardMetadataType::name>::value ::decode(value, valueSize) \
345 .value(); \
346 break
347
dumpBufferCommon(DumpBufferResult * outResult,AIMapper_MetadataType metadataType,const void * value,size_t valueSize)348 static void dumpBufferCommon(DumpBufferResult* outResult, AIMapper_MetadataType metadataType,
349 const void* value, size_t valueSize) {
350 if (!isStandardMetadata(metadataType)) {
351 return;
352 }
353 StandardMetadataType type = (StandardMetadataType)metadataType.value;
354 switch (type) {
355 DECODE_TO(BUFFER_ID, outResult->bufferId);
356 DECODE_TO(NAME, outResult->name);
357 DECODE_TO(WIDTH, outResult->width);
358 DECODE_TO(HEIGHT, outResult->height);
359 DECODE_TO(LAYER_COUNT, outResult->layerCount);
360 DECODE_TO(PIXEL_FORMAT_REQUESTED, outResult->pixelFormatRequested);
361 DECODE_TO(PIXEL_FORMAT_FOURCC, outResult->pixelFormatFourCC);
362 DECODE_TO(PIXEL_FORMAT_MODIFIER, outResult->pixelFormatModifier);
363 DECODE_TO(USAGE, outResult->usage);
364 DECODE_TO(DATASPACE, outResult->dataspace);
365 DECODE_TO(ALLOCATION_SIZE, outResult->allocationSize);
366 DECODE_TO(PROTECTED_CONTENT, outResult->protectedContent);
367 DECODE_TO(COMPRESSION, outResult->compression);
368 DECODE_TO(INTERLACED, outResult->interlaced);
369 DECODE_TO(CHROMA_SITING, outResult->chromaSiting);
370 DECODE_TO(PLANE_LAYOUTS, outResult->planeLayouts);
371 default:
372 break;
373 }
374 }
375
376 #undef DECODE_TO
377
378 template <typename EnumT, typename = std::enable_if_t<std::is_enum<EnumT>{}>>
to_underlying(EnumT e)379 constexpr std::underlying_type_t<EnumT> to_underlying(EnumT e) noexcept {
380 return static_cast<std::underlying_type_t<EnumT>>(e);
381 }
382
writeDumpToStream(const DumpBufferResult & bufferDump,std::ostream & outDump,bool less)383 static void writeDumpToStream(const DumpBufferResult& bufferDump, std::ostream& outDump,
384 bool less) {
385 double allocationSizeKiB = static_cast<double>(bufferDump.allocationSize) / 1024;
386
387 outDump << "+ name:" << bufferDump.name << ", id:" << bufferDump.bufferId
388 << ", size:" << std::fixed << allocationSizeKiB << "KiB, w/h:" << bufferDump.width
389 << "x" << bufferDump.height << ", usage: 0x" << std::hex
390 << to_underlying(bufferDump.usage) << std::dec
391 << ", req fmt:" << to_underlying(bufferDump.pixelFormatRequested)
392 << ", fourcc/mod:" << bufferDump.pixelFormatFourCC << "/"
393 << bufferDump.pixelFormatModifier << ", dataspace: 0x" << std::hex
394 << to_underlying(bufferDump.dataspace) << std::dec << ", compressed: ";
395
396 if (less) {
397 bool isCompressed = !gralloc4::isStandardCompression(bufferDump.compression) ||
398 (gralloc4::getStandardCompressionValue(bufferDump.compression) !=
399 ui::Compression::NONE);
400 outDump << std::boolalpha << isCompressed << "\n";
401 } else {
402 outDump << gralloc4::getCompressionName(bufferDump.compression) << "\n";
403 }
404
405 if (!less) {
406 bool firstPlane = true;
407 for (const auto& planeLayout : bufferDump.planeLayouts) {
408 if (firstPlane) {
409 firstPlane = false;
410 outDump << "\tplanes: ";
411 } else {
412 outDump << "\t ";
413 }
414
415 for (size_t i = 0; i < planeLayout.components.size(); i++) {
416 const auto& planeLayoutComponent = planeLayout.components[i];
417 outDump << gralloc4::getPlaneLayoutComponentTypeName(planeLayoutComponent.type);
418 if (i < planeLayout.components.size() - 1) {
419 outDump << "/";
420 } else {
421 outDump << ":\t";
422 }
423 }
424 outDump << " w/h:" << planeLayout.widthInSamples << "x" << planeLayout.heightInSamples
425 << ", stride:" << planeLayout.strideInBytes
426 << " bytes, size:" << planeLayout.totalSizeInBytes;
427 outDump << ", inc:" << planeLayout.sampleIncrementInBits
428 << " bits, subsampling w/h:" << planeLayout.horizontalSubsampling << "x"
429 << planeLayout.verticalSubsampling;
430 outDump << "\n";
431 }
432
433 outDump << "\tlayer cnt: " << bufferDump.layerCount
434 << ", protected content: " << bufferDump.protectedContent
435 << ", interlaced: " << gralloc4::getInterlacedName(bufferDump.interlaced)
436 << ", chroma siting:" << gralloc4::getChromaSitingName(bufferDump.chromaSiting)
437 << "\n";
438 }
439 }
440
dumpBuffer(buffer_handle_t bufferHandle,bool less) const441 std::string Gralloc5Mapper::dumpBuffer(buffer_handle_t bufferHandle, bool less) const {
442 DumpBufferResult bufferInfo;
443 AIMapper_DumpBufferCallback dumpBuffer = [](void* contextPtr,
444 AIMapper_MetadataType metadataType,
445 const void* _Nonnull value, size_t valueSize) {
446 DumpBufferResult* context = reinterpret_cast<DumpBufferResult*>(contextPtr);
447 dumpBufferCommon(context, metadataType, value, valueSize);
448 };
449 AIMapper_Error error = mMapper->v5.dumpBuffer(bufferHandle, dumpBuffer, &bufferInfo);
450 if (error != AIMAPPER_ERROR_NONE) {
451 ALOGE("Error dumping buffer: %d", error);
452 return std::string{};
453 }
454 std::ostringstream stream;
455 stream.precision(2);
456 writeDumpToStream(bufferInfo, stream, less);
457 return stream.str();
458 }
459
dumpBuffers(bool less) const460 std::string Gralloc5Mapper::dumpBuffers(bool less) const {
461 class DumpAllBuffersContext {
462 private:
463 bool mHasPending = false;
464 DumpBufferResult mPending;
465 std::vector<DumpBufferResult> mResults;
466
467 public:
468 DumpAllBuffersContext() { mResults.reserve(10); }
469
470 void commit() {
471 if (mHasPending) {
472 mResults.push_back(mPending);
473 mHasPending = false;
474 }
475 }
476
477 DumpBufferResult* write() {
478 mHasPending = true;
479 return &mPending;
480 }
481
482 const std::vector<DumpBufferResult>& results() {
483 commit();
484 return mResults;
485 }
486 } context;
487
488 AIMapper_BeginDumpBufferCallback beginCallback = [](void* contextPtr) {
489 DumpAllBuffersContext* context = reinterpret_cast<DumpAllBuffersContext*>(contextPtr);
490 context->commit();
491 };
492
493 AIMapper_DumpBufferCallback dumpBuffer = [](void* contextPtr,
494 AIMapper_MetadataType metadataType,
495 const void* _Nonnull value, size_t valueSize) {
496 DumpAllBuffersContext* context = reinterpret_cast<DumpAllBuffersContext*>(contextPtr);
497 dumpBufferCommon(context->write(), metadataType, value, valueSize);
498 };
499
500 AIMapper_Error error = mMapper->v5.dumpAllBuffers(beginCallback, dumpBuffer, &context);
501 if (error != AIMAPPER_ERROR_NONE) {
502 ALOGE("Error dumping buffers: %d", error);
503 return std::string{};
504 }
505 uint64_t totalAllocationSize = 0;
506 std::ostringstream stream;
507 stream.precision(2);
508 stream << "Imported gralloc buffers:\n";
509
510 for (const auto& bufferDump : context.results()) {
511 writeDumpToStream(bufferDump, stream, less);
512 totalAllocationSize += bufferDump.allocationSize;
513 }
514
515 double totalAllocationSizeKiB = static_cast<double>(totalAllocationSize) / 1024;
516 stream << "Total imported by gralloc: " << totalAllocationSizeKiB << "KiB\n";
517 return stream.str();
518 }
519
importBuffer(const native_handle_t * rawHandle,buffer_handle_t * outBufferHandle) const520 status_t Gralloc5Mapper::importBuffer(const native_handle_t *rawHandle,
521 buffer_handle_t *outBufferHandle) const {
522 return mMapper->v5.importBuffer(rawHandle, outBufferHandle);
523 }
524
freeBuffer(buffer_handle_t bufferHandle) const525 void Gralloc5Mapper::freeBuffer(buffer_handle_t bufferHandle) const {
526 mMapper->v5.freeBuffer(bufferHandle);
527 }
528
validateBufferSize(buffer_handle_t bufferHandle,uint32_t width,uint32_t height,PixelFormat format,uint32_t layerCount,uint64_t usage,uint32_t stride) const529 status_t Gralloc5Mapper::validateBufferSize(buffer_handle_t bufferHandle, uint32_t width,
530 uint32_t height, PixelFormat format,
531 uint32_t layerCount, uint64_t usage,
532 uint32_t stride) const {
533 {
534 auto value = getStandardMetadata<StandardMetadataType::WIDTH>(mMapper, bufferHandle);
535 if (width != value) {
536 ALOGW("Width didn't match, expected %d got %" PRId64, width, value.value_or(-1));
537 return BAD_VALUE;
538 }
539 }
540 {
541 auto value = getStandardMetadata<StandardMetadataType::HEIGHT>(mMapper, bufferHandle);
542 if (height != value) {
543 ALOGW("Height didn't match, expected %d got %" PRId64, height, value.value_or(-1));
544 return BAD_VALUE;
545 }
546 }
547 {
548 auto expected = static_cast<APixelFormat>(format);
549 if (expected != APixelFormat::IMPLEMENTATION_DEFINED) {
550 auto value =
551 getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_REQUESTED>(mMapper,
552 bufferHandle);
553 if (expected != value) {
554 ALOGW("Format didn't match, expected %d got %s", format,
555 value.has_value() ? toString(*value).c_str() : "<null>");
556 return BAD_VALUE;
557 }
558 }
559 }
560 {
561 auto value = getStandardMetadata<StandardMetadataType::LAYER_COUNT>(mMapper, bufferHandle);
562 if (layerCount != value) {
563 ALOGW("Layer count didn't match, expected %d got %" PRId64, layerCount,
564 value.value_or(-1));
565 return BAD_VALUE;
566 }
567 }
568 // TODO: This can false-positive fail if the allocator adjusted the USAGE bits internally
569 // Investigate further & re-enable or remove, but for now ignoring usage should be OK
570 (void)usage;
571 // {
572 // auto value = getStandardMetadata<StandardMetadataType::USAGE>(mMapper, bufferHandle);
573 // if (static_cast<BufferUsage>(usage) != value) {
574 // ALOGW("Usage didn't match, expected %" PRIu64 " got %" PRId64, usage,
575 // static_cast<int64_t>(value.value_or(BufferUsage::CPU_READ_NEVER)));
576 // return BAD_VALUE;
577 // }
578 // }
579 {
580 auto value = getStandardMetadata<StandardMetadataType::STRIDE>(mMapper, bufferHandle);
581 if (stride != value) {
582 ALOGW("Stride didn't match, expected %" PRIu32 " got %" PRId32, stride,
583 value.value_or(-1));
584 return BAD_VALUE;
585 }
586 }
587 return OK;
588 }
589
getTransportSize(buffer_handle_t bufferHandle,uint32_t * outNumFds,uint32_t * outNumInts) const590 void Gralloc5Mapper::getTransportSize(buffer_handle_t bufferHandle, uint32_t *outNumFds,
591 uint32_t *outNumInts) const {
592 mMapper->v5.getTransportSize(bufferHandle, outNumFds, outNumInts);
593 }
594
lock(buffer_handle_t bufferHandle,uint64_t usage,const Rect & bounds,int acquireFence,void ** outData,int32_t * outBytesPerPixel,int32_t * outBytesPerStride) const595 status_t Gralloc5Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect &bounds,
596 int acquireFence, void **outData, int32_t *outBytesPerPixel,
597 int32_t *outBytesPerStride) const {
598 if (outBytesPerPixel) *outBytesPerPixel = -1;
599 if (outBytesPerStride) *outBytesPerStride = -1;
600
601 auto status = mMapper->v5.lock(bufferHandle, usage, bounds, acquireFence, outData);
602
603 ALOGW_IF(status != AIMAPPER_ERROR_NONE, "lock(%p, ...) failed: %d", bufferHandle, status);
604 return static_cast<status_t>(status);
605 }
606
lock(buffer_handle_t bufferHandle,uint64_t usage,const Rect & bounds,int acquireFence,android_ycbcr * outYcbcr) const607 status_t Gralloc5Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect &bounds,
608 int acquireFence, android_ycbcr *outYcbcr) const {
609 if (!outYcbcr) {
610 return BAD_VALUE;
611 }
612
613 // TODO(b/262279301): Change the return type of ::unlock to unique_fd instead of int so that
614 // ignoring the return value "just works" instead
615 auto unlock = [this](buffer_handle_t bufferHandle) {
616 int fence = this->unlock(bufferHandle);
617 if (fence != -1) {
618 ::close(fence);
619 }
620 };
621
622 std::vector<ui::PlaneLayout> planeLayouts;
623 status_t error = getPlaneLayouts(bufferHandle, &planeLayouts);
624 if (error != NO_ERROR) {
625 return error;
626 }
627
628 void *data = nullptr;
629 error = lock(bufferHandle, usage, bounds, acquireFence, &data, nullptr, nullptr);
630 if (error != NO_ERROR) {
631 return error;
632 }
633
634 android_ycbcr ycbcr;
635
636 ycbcr.y = nullptr;
637 ycbcr.cb = nullptr;
638 ycbcr.cr = nullptr;
639 ycbcr.ystride = 0;
640 ycbcr.cstride = 0;
641 ycbcr.chroma_step = 0;
642
643 for (const auto &planeLayout : planeLayouts) {
644 for (const auto &planeLayoutComponent : planeLayout.components) {
645 if (!gralloc4::isStandardPlaneLayoutComponentType(planeLayoutComponent.type)) {
646 continue;
647 }
648
649 uint8_t *tmpData = static_cast<uint8_t *>(data) + planeLayout.offsetInBytes;
650
651 // Note that `offsetInBits` may not be a multiple of 8 for packed formats (e.g. P010)
652 // but we still want to point to the start of the first byte.
653 tmpData += (planeLayoutComponent.offsetInBits / 8);
654
655 uint64_t sampleIncrementInBytes;
656
657 auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
658 switch (type) {
659 case PlaneLayoutComponentType::Y:
660 if ((ycbcr.y != nullptr) || (planeLayout.sampleIncrementInBits % 8 != 0)) {
661 unlock(bufferHandle);
662 return BAD_VALUE;
663 }
664 ycbcr.y = tmpData;
665 ycbcr.ystride = planeLayout.strideInBytes;
666 break;
667
668 case PlaneLayoutComponentType::CB:
669 case PlaneLayoutComponentType::CR:
670 if (planeLayout.sampleIncrementInBits % 8 != 0) {
671 unlock(bufferHandle);
672 return BAD_VALUE;
673 }
674
675 sampleIncrementInBytes = planeLayout.sampleIncrementInBits / 8;
676 if ((sampleIncrementInBytes != 1) && (sampleIncrementInBytes != 2) &&
677 (sampleIncrementInBytes != 4)) {
678 unlock(bufferHandle);
679 return BAD_VALUE;
680 }
681
682 if (ycbcr.cstride == 0 && ycbcr.chroma_step == 0) {
683 ycbcr.cstride = planeLayout.strideInBytes;
684 ycbcr.chroma_step = sampleIncrementInBytes;
685 } else {
686 if ((static_cast<int64_t>(ycbcr.cstride) != planeLayout.strideInBytes) ||
687 (ycbcr.chroma_step != sampleIncrementInBytes)) {
688 unlock(bufferHandle);
689 return BAD_VALUE;
690 }
691 }
692
693 if (type == PlaneLayoutComponentType::CB) {
694 if (ycbcr.cb != nullptr) {
695 unlock(bufferHandle);
696 return BAD_VALUE;
697 }
698 ycbcr.cb = tmpData;
699 } else {
700 if (ycbcr.cr != nullptr) {
701 unlock(bufferHandle);
702 return BAD_VALUE;
703 }
704 ycbcr.cr = tmpData;
705 }
706 break;
707 default:
708 break;
709 };
710 }
711 }
712
713 *outYcbcr = ycbcr;
714 return OK;
715 }
716
unlock(buffer_handle_t bufferHandle) const717 int Gralloc5Mapper::unlock(buffer_handle_t bufferHandle) const {
718 int fence = -1;
719 AIMapper_Error error = mMapper->v5.unlock(bufferHandle, &fence);
720 if (error != AIMAPPER_ERROR_NONE) {
721 ALOGW("unlock failed with error %d", error);
722 }
723 return fence;
724 }
725
isSupported(uint32_t width,uint32_t height,PixelFormat format,uint32_t layerCount,uint64_t usage,bool * outSupported) const726 status_t Gralloc5Mapper::isSupported(uint32_t width, uint32_t height, PixelFormat format,
727 uint32_t layerCount, uint64_t usage,
728 bool *outSupported) const {
729 auto descriptorInfo = makeDescriptor("", width, height, format, layerCount, usage);
730 if (!descriptorInfo) {
731 *outSupported = false;
732 return OK;
733 }
734 auto status = getInstance().allocator->isSupported(*descriptorInfo, outSupported);
735 if (!status.isOk()) {
736 ALOGW("IAllocator::isSupported error %d (%s)", status.getStatus(), status.getMessage());
737 *outSupported = false;
738 }
739 return OK;
740 }
741
getBufferId(buffer_handle_t bufferHandle,uint64_t * outBufferId) const742 status_t Gralloc5Mapper::getBufferId(buffer_handle_t bufferHandle, uint64_t *outBufferId) const {
743 auto value = getStandardMetadata<StandardMetadataType::BUFFER_ID>(mMapper, bufferHandle);
744 if (value.has_value()) {
745 *outBufferId = *value;
746 return OK;
747 }
748 return UNKNOWN_TRANSACTION;
749 }
750
getName(buffer_handle_t bufferHandle,std::string * outName) const751 status_t Gralloc5Mapper::getName(buffer_handle_t bufferHandle, std::string *outName) const {
752 auto value = getStandardMetadata<StandardMetadataType::NAME>(mMapper, bufferHandle);
753 if (value.has_value()) {
754 *outName = *value;
755 return OK;
756 }
757 return UNKNOWN_TRANSACTION;
758 }
759
getWidth(buffer_handle_t bufferHandle,uint64_t * outWidth) const760 status_t Gralloc5Mapper::getWidth(buffer_handle_t bufferHandle, uint64_t *outWidth) const {
761 auto value = getStandardMetadata<StandardMetadataType::WIDTH>(mMapper, bufferHandle);
762 if (value.has_value()) {
763 *outWidth = *value;
764 return OK;
765 }
766 return UNKNOWN_TRANSACTION;
767 }
768
getHeight(buffer_handle_t bufferHandle,uint64_t * outHeight) const769 status_t Gralloc5Mapper::getHeight(buffer_handle_t bufferHandle, uint64_t *outHeight) const {
770 auto value = getStandardMetadata<StandardMetadataType::HEIGHT>(mMapper, bufferHandle);
771 if (value.has_value()) {
772 *outHeight = *value;
773 return OK;
774 }
775 return UNKNOWN_TRANSACTION;
776 }
777
getLayerCount(buffer_handle_t bufferHandle,uint64_t * outLayerCount) const778 status_t Gralloc5Mapper::getLayerCount(buffer_handle_t bufferHandle,
779 uint64_t *outLayerCount) const {
780 auto value = getStandardMetadata<StandardMetadataType::LAYER_COUNT>(mMapper, bufferHandle);
781 if (value.has_value()) {
782 *outLayerCount = *value;
783 return OK;
784 }
785 return UNKNOWN_TRANSACTION;
786 }
787
getPixelFormatRequested(buffer_handle_t bufferHandle,ui::PixelFormat * outPixelFormatRequested) const788 status_t Gralloc5Mapper::getPixelFormatRequested(buffer_handle_t bufferHandle,
789 ui::PixelFormat *outPixelFormatRequested) const {
790 auto value = getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_REQUESTED>(mMapper,
791 bufferHandle);
792 if (value.has_value()) {
793 *outPixelFormatRequested = static_cast<ui::PixelFormat>(*value);
794 return OK;
795 }
796 return UNKNOWN_TRANSACTION;
797 }
798
getPixelFormatFourCC(buffer_handle_t bufferHandle,uint32_t * outPixelFormatFourCC) const799 status_t Gralloc5Mapper::getPixelFormatFourCC(buffer_handle_t bufferHandle,
800 uint32_t *outPixelFormatFourCC) const {
801 auto value =
802 getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_FOURCC>(mMapper, bufferHandle);
803 if (value.has_value()) {
804 *outPixelFormatFourCC = *value;
805 return OK;
806 }
807 return UNKNOWN_TRANSACTION;
808 }
809
getPixelFormatModifier(buffer_handle_t bufferHandle,uint64_t * outPixelFormatModifier) const810 status_t Gralloc5Mapper::getPixelFormatModifier(buffer_handle_t bufferHandle,
811 uint64_t *outPixelFormatModifier) const {
812 auto value =
813 getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_MODIFIER>(mMapper, bufferHandle);
814 if (value.has_value()) {
815 *outPixelFormatModifier = *value;
816 return OK;
817 }
818 return UNKNOWN_TRANSACTION;
819 }
820
getUsage(buffer_handle_t bufferHandle,uint64_t * outUsage) const821 status_t Gralloc5Mapper::getUsage(buffer_handle_t bufferHandle, uint64_t *outUsage) const {
822 auto value = getStandardMetadata<StandardMetadataType::USAGE>(mMapper, bufferHandle);
823 if (value.has_value()) {
824 *outUsage = static_cast<uint64_t>(*value);
825 return OK;
826 }
827 return UNKNOWN_TRANSACTION;
828 }
829
getAllocationSize(buffer_handle_t bufferHandle,uint64_t * outAllocationSize) const830 status_t Gralloc5Mapper::getAllocationSize(buffer_handle_t bufferHandle,
831 uint64_t *outAllocationSize) const {
832 auto value = getStandardMetadata<StandardMetadataType::ALLOCATION_SIZE>(mMapper, bufferHandle);
833 if (value.has_value()) {
834 *outAllocationSize = *value;
835 return OK;
836 }
837 return UNKNOWN_TRANSACTION;
838 }
839
getProtectedContent(buffer_handle_t bufferHandle,uint64_t * outProtectedContent) const840 status_t Gralloc5Mapper::getProtectedContent(buffer_handle_t bufferHandle,
841 uint64_t *outProtectedContent) const {
842 auto value =
843 getStandardMetadata<StandardMetadataType::PROTECTED_CONTENT>(mMapper, bufferHandle);
844 if (value.has_value()) {
845 *outProtectedContent = *value;
846 return OK;
847 }
848 return UNKNOWN_TRANSACTION;
849 }
850
getCompression(buffer_handle_t bufferHandle,aidl::android::hardware::graphics::common::ExtendableType * outCompression) const851 status_t Gralloc5Mapper::getCompression(
852 buffer_handle_t bufferHandle,
853 aidl::android::hardware::graphics::common::ExtendableType *outCompression) const {
854 auto value = getStandardMetadata<StandardMetadataType::COMPRESSION>(mMapper, bufferHandle);
855 if (value.has_value()) {
856 *outCompression = *value;
857 return OK;
858 }
859 return UNKNOWN_TRANSACTION;
860 }
861
getCompression(buffer_handle_t bufferHandle,ui::Compression * outCompression) const862 status_t Gralloc5Mapper::getCompression(buffer_handle_t bufferHandle,
863 ui::Compression *outCompression) const {
864 auto value = getStandardMetadata<StandardMetadataType::COMPRESSION>(mMapper, bufferHandle);
865 if (!value.has_value()) {
866 return UNKNOWN_TRANSACTION;
867 }
868 if (!gralloc4::isStandardCompression(*value)) {
869 return BAD_TYPE;
870 }
871 *outCompression = gralloc4::getStandardCompressionValue(*value);
872 return OK;
873 }
874
getInterlaced(buffer_handle_t bufferHandle,aidl::android::hardware::graphics::common::ExtendableType * outInterlaced) const875 status_t Gralloc5Mapper::getInterlaced(
876 buffer_handle_t bufferHandle,
877 aidl::android::hardware::graphics::common::ExtendableType *outInterlaced) const {
878 auto value = getStandardMetadata<StandardMetadataType::INTERLACED>(mMapper, bufferHandle);
879 if (value.has_value()) {
880 *outInterlaced = *value;
881 return OK;
882 }
883 return UNKNOWN_TRANSACTION;
884 }
885
getInterlaced(buffer_handle_t bufferHandle,ui::Interlaced * outInterlaced) const886 status_t Gralloc5Mapper::getInterlaced(buffer_handle_t bufferHandle,
887 ui::Interlaced *outInterlaced) const {
888 if (!outInterlaced) {
889 return BAD_VALUE;
890 }
891 ExtendableType interlaced;
892 status_t error = getInterlaced(bufferHandle, &interlaced);
893 if (error) {
894 return error;
895 }
896 if (!gralloc4::isStandardInterlaced(interlaced)) {
897 return BAD_TYPE;
898 }
899 *outInterlaced = gralloc4::getStandardInterlacedValue(interlaced);
900 return NO_ERROR;
901 }
902
getChromaSiting(buffer_handle_t bufferHandle,aidl::android::hardware::graphics::common::ExtendableType * outChromaSiting) const903 status_t Gralloc5Mapper::getChromaSiting(
904 buffer_handle_t bufferHandle,
905 aidl::android::hardware::graphics::common::ExtendableType *outChromaSiting) const {
906 auto value = getStandardMetadata<StandardMetadataType::CHROMA_SITING>(mMapper, bufferHandle);
907 if (value.has_value()) {
908 *outChromaSiting = *value;
909 return OK;
910 }
911 return UNKNOWN_TRANSACTION;
912 }
913
getChromaSiting(buffer_handle_t bufferHandle,ui::ChromaSiting * outChromaSiting) const914 status_t Gralloc5Mapper::getChromaSiting(buffer_handle_t bufferHandle,
915 ui::ChromaSiting *outChromaSiting) const {
916 if (!outChromaSiting) {
917 return BAD_VALUE;
918 }
919 ExtendableType chromaSiting;
920 status_t error = getChromaSiting(bufferHandle, &chromaSiting);
921 if (error) {
922 return error;
923 }
924 if (!gralloc4::isStandardChromaSiting(chromaSiting)) {
925 return BAD_TYPE;
926 }
927 *outChromaSiting = gralloc4::getStandardChromaSitingValue(chromaSiting);
928 return NO_ERROR;
929 }
930
getPlaneLayouts(buffer_handle_t bufferHandle,std::vector<ui::PlaneLayout> * outPlaneLayouts) const931 status_t Gralloc5Mapper::getPlaneLayouts(buffer_handle_t bufferHandle,
932 std::vector<ui::PlaneLayout> *outPlaneLayouts) const {
933 auto value = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(mMapper, bufferHandle);
934 if (value.has_value()) {
935 *outPlaneLayouts = *value;
936 return OK;
937 }
938 return UNKNOWN_TRANSACTION;
939 }
940
getDataspace(buffer_handle_t bufferHandle,ui::Dataspace * outDataspace) const941 status_t Gralloc5Mapper::getDataspace(buffer_handle_t bufferHandle,
942 ui::Dataspace *outDataspace) const {
943 auto value = getStandardMetadata<StandardMetadataType::DATASPACE>(mMapper, bufferHandle);
944 if (value.has_value()) {
945 *outDataspace = static_cast<ui::Dataspace>(*value);
946 return OK;
947 }
948 return UNKNOWN_TRANSACTION;
949 }
950
setDataspace(buffer_handle_t bufferHandle,ui::Dataspace dataspace) const951 status_t Gralloc5Mapper::setDataspace(buffer_handle_t bufferHandle, ui::Dataspace dataspace) const {
952 return setStandardMetadata<StandardMetadataType::DATASPACE>(mMapper, bufferHandle,
953 static_cast<Dataspace>(dataspace));
954 }
955
getBlendMode(buffer_handle_t bufferHandle,ui::BlendMode * outBlendMode) const956 status_t Gralloc5Mapper::getBlendMode(buffer_handle_t bufferHandle,
957 ui::BlendMode *outBlendMode) const {
958 auto value = getStandardMetadata<StandardMetadataType::BLEND_MODE>(mMapper, bufferHandle);
959 if (value.has_value()) {
960 *outBlendMode = static_cast<ui::BlendMode>(*value);
961 return OK;
962 }
963 return UNKNOWN_TRANSACTION;
964 }
965
getSmpte2086(buffer_handle_t bufferHandle,std::optional<ui::Smpte2086> * outSmpte2086) const966 status_t Gralloc5Mapper::getSmpte2086(buffer_handle_t bufferHandle,
967 std::optional<ui::Smpte2086> *outSmpte2086) const {
968 auto value = getStandardMetadata<StandardMetadataType::SMPTE2086>(mMapper, bufferHandle);
969 if (value.has_value()) {
970 *outSmpte2086 = *value;
971 return OK;
972 }
973 return UNKNOWN_TRANSACTION;
974 }
975
setSmpte2086(buffer_handle_t bufferHandle,std::optional<ui::Smpte2086> smpte2086) const976 status_t Gralloc5Mapper::setSmpte2086(buffer_handle_t bufferHandle,
977 std::optional<ui::Smpte2086> smpte2086) const {
978 return setStandardMetadata<StandardMetadataType::SMPTE2086>(mMapper, bufferHandle, smpte2086);
979 }
980
getCta861_3(buffer_handle_t bufferHandle,std::optional<ui::Cta861_3> * outCta861_3) const981 status_t Gralloc5Mapper::getCta861_3(buffer_handle_t bufferHandle,
982 std::optional<ui::Cta861_3> *outCta861_3) const {
983 auto value = getStandardMetadata<StandardMetadataType::CTA861_3>(mMapper, bufferHandle);
984 if (value.has_value()) {
985 *outCta861_3 = *value;
986 return OK;
987 }
988 return UNKNOWN_TRANSACTION;
989 }
990
setCta861_3(buffer_handle_t bufferHandle,std::optional<ui::Cta861_3> cta861_3) const991 status_t Gralloc5Mapper::setCta861_3(buffer_handle_t bufferHandle,
992 std::optional<ui::Cta861_3> cta861_3) const {
993 return setStandardMetadata<StandardMetadataType::CTA861_3>(mMapper, bufferHandle, cta861_3);
994 }
995
getSmpte2094_40(buffer_handle_t bufferHandle,std::optional<std::vector<uint8_t>> * outSmpte2094_40) const996 status_t Gralloc5Mapper::getSmpte2094_40(
997 buffer_handle_t bufferHandle, std::optional<std::vector<uint8_t>> *outSmpte2094_40) const {
998 auto value = getStandardMetadata<StandardMetadataType::SMPTE2094_40>(mMapper, bufferHandle);
999 if (value.has_value()) {
1000 *outSmpte2094_40 = std::move(*value);
1001 return OK;
1002 }
1003 return UNKNOWN_TRANSACTION;
1004 }
1005
setSmpte2094_40(buffer_handle_t bufferHandle,std::optional<std::vector<uint8_t>> smpte2094_40) const1006 status_t Gralloc5Mapper::setSmpte2094_40(buffer_handle_t bufferHandle,
1007 std::optional<std::vector<uint8_t>> smpte2094_40) const {
1008 return setStandardMetadata<StandardMetadataType::SMPTE2094_40>(mMapper, bufferHandle,
1009 smpte2094_40);
1010 }
1011
getSmpte2094_10(buffer_handle_t bufferHandle,std::optional<std::vector<uint8_t>> * outSmpte2094_10) const1012 status_t Gralloc5Mapper::getSmpte2094_10(
1013 buffer_handle_t bufferHandle, std::optional<std::vector<uint8_t>> *outSmpte2094_10) const {
1014 auto value = getStandardMetadata<StandardMetadataType::SMPTE2094_10>(mMapper, bufferHandle);
1015 if (value.has_value()) {
1016 *outSmpte2094_10 = std::move(*value);
1017 return OK;
1018 }
1019 return UNKNOWN_TRANSACTION;
1020 }
1021
setSmpte2094_10(buffer_handle_t bufferHandle,std::optional<std::vector<uint8_t>> smpte2094_10) const1022 status_t Gralloc5Mapper::setSmpte2094_10(buffer_handle_t bufferHandle,
1023 std::optional<std::vector<uint8_t>> smpte2094_10) const {
1024 return setStandardMetadata<StandardMetadataType::SMPTE2094_10>(mMapper, bufferHandle,
1025 smpte2094_10);
1026 }
1027
1028 } // namespace android