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