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