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