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