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