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