1 /*
2 * Copyright 2022 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7 #include "Allocator.h"
8
9 #include <aidl/android/hardware/graphics/allocator/AllocationError.h>
10 #include <aidlcommonsupport/NativeHandle.h>
11 #include <android-base/logging.h>
12 #include <android/binder_ibinder_platform.h>
13 #include <gralloctypes/Gralloc4.h>
14 #include <log/log.h>
15
16 #include "cros_gralloc/gralloc4/CrosGralloc4Utils.h"
17
18 using aidl::android::hardware::common::NativeHandle;
19 using BufferDescriptorInfoV4 =
20 android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo;
21
22 static const std::string STANDARD_METADATA_DATASPACE = "android.hardware.graphics.common.Dataspace";
23
24 namespace aidl::android::hardware::graphics::allocator::impl {
25 namespace {
26
ToBinderStatus(AllocationError error)27 inline ndk::ScopedAStatus ToBinderStatus(AllocationError error) {
28 return ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(error));
29 }
30
convertToCrosDescriptor(const BufferDescriptorInfo & info,struct cros_gralloc_buffer_descriptor & crosDescriptor)31 ndk::ScopedAStatus convertToCrosDescriptor(const BufferDescriptorInfo& info,
32 struct cros_gralloc_buffer_descriptor& crosDescriptor) {
33 const BufferDescriptorInfoV4 mapperV4Descriptor = {
34 .name{reinterpret_cast<const char*>(info.name.data())},
35 .width = static_cast<uint32_t>(info.width),
36 .height = static_cast<uint32_t>(info.height),
37 .layerCount = static_cast<uint32_t>(info.layerCount),
38 .format = static_cast<::android::hardware::graphics::common::V1_2::PixelFormat>(info.format),
39 .usage = static_cast<uint64_t>(info.usage),
40 .reservedSize = 0,
41 };
42 if (convertToCrosDescriptor(mapperV4Descriptor, &crosDescriptor)) {
43 return ToBinderStatus(AllocationError::UNSUPPORTED);
44 }
45
46 for (const auto& option : info.additionalOptions) {
47 if (option.name != STANDARD_METADATA_DATASPACE) {
48 return ToBinderStatus(AllocationError::UNSUPPORTED);
49 }
50 crosDescriptor.dataspace = static_cast<common::Dataspace>(option.value);
51 }
52
53 return ndk::ScopedAStatus::ok();
54 }
55
56 } // namespace
57
init()58 bool Allocator::init() {
59 mDriver = cros_gralloc_driver::get_instance();
60 return mDriver != nullptr;
61 }
62
releaseBufferAndHandle(native_handle_t * handle)63 void Allocator::releaseBufferAndHandle(native_handle_t* handle) {
64 mDriver->release(handle);
65 native_handle_close(handle);
66 native_handle_delete(handle);
67 }
68
allocate(const std::vector<uint8_t> & encodedDescriptor,int32_t count,allocator::AllocationResult * outResult)69 ndk::ScopedAStatus Allocator::allocate(const std::vector<uint8_t>& encodedDescriptor, int32_t count,
70 allocator::AllocationResult* outResult) {
71 if (!mDriver) {
72 ALOGE("Failed to allocate. Driver is uninitialized.\n");
73 return ToBinderStatus(AllocationError::NO_RESOURCES);
74 }
75
76 BufferDescriptorInfoV4 mapperV4Descriptor;
77
78 int ret = ::android::gralloc4::decodeBufferDescriptorInfo(encodedDescriptor, &mapperV4Descriptor);
79 if (ret) {
80 ALOGE("Failed to allocate. Failed to decode buffer descriptor: %d.\n", ret);
81 return ToBinderStatus(AllocationError::BAD_DESCRIPTOR);
82 }
83
84 struct cros_gralloc_buffer_descriptor crosDescriptor = {};
85 if (convertToCrosDescriptor(mapperV4Descriptor, &crosDescriptor)) {
86 return ToBinderStatus(AllocationError::UNSUPPORTED);
87 }
88
89 return allocate(crosDescriptor, count, outResult);
90 }
91
allocate2(const BufferDescriptorInfo & descriptor,int32_t count,allocator::AllocationResult * outResult)92 ndk::ScopedAStatus Allocator::allocate2(const BufferDescriptorInfo& descriptor, int32_t count,
93 allocator::AllocationResult* outResult) {
94 if (!mDriver) {
95 ALOGE("Failed to allocate. Driver is uninitialized.\n");
96 return ToBinderStatus(AllocationError::NO_RESOURCES);
97 }
98
99 struct cros_gralloc_buffer_descriptor crosDescriptor = {};
100
101 ndk::ScopedAStatus status = convertToCrosDescriptor(descriptor, crosDescriptor);
102 if (!status.isOk()) {
103 return status;
104 }
105
106 return allocate(crosDescriptor, count, outResult);
107 }
108
allocate(const struct cros_gralloc_buffer_descriptor & descriptor,int32_t count,allocator::AllocationResult * outResult)109 ndk::ScopedAStatus Allocator::allocate(const struct cros_gralloc_buffer_descriptor& descriptor, int32_t count,
110 allocator::AllocationResult* outResult) {
111 if (!mDriver) {
112 ALOGE("Failed to allocate. Driver is uninitialized.\n");
113 return ToBinderStatus(AllocationError::NO_RESOURCES);
114 }
115
116 std::vector<native_handle_t*> handles;
117 handles.resize(count, nullptr);
118
119 for (int32_t i = 0; i < count; i++) {
120 ndk::ScopedAStatus status = allocateBuffer(descriptor, &outResult->stride, &handles[i]);
121 if (!status.isOk()) {
122 for (int32_t j = 0; j < i; j++) {
123 releaseBufferAndHandle(handles[j]);
124 }
125 return status;
126 }
127 }
128
129 outResult->buffers.resize(count);
130 for (int32_t i = 0; i < count; i++) {
131 auto handle = handles[i];
132 outResult->buffers[i] = ::android::dupToAidl(handle);
133 releaseBufferAndHandle(handle);
134 }
135
136 return ndk::ScopedAStatus::ok();
137 }
138
allocateBuffer(const struct cros_gralloc_buffer_descriptor & descriptor,int32_t * outStride,native_handle_t ** outHandle)139 ndk::ScopedAStatus Allocator::allocateBuffer(const struct cros_gralloc_buffer_descriptor& descriptor, int32_t* outStride,
140 native_handle_t** outHandle) {
141 if (!mDriver) {
142 ALOGE("Failed to allocate. Driver is uninitialized.\n");
143 return ToBinderStatus(AllocationError::NO_RESOURCES);
144 }
145
146 if (!mDriver->is_supported(&descriptor)) {
147 const std::string drmFormatString =
148 get_drm_format_string(descriptor.drm_format);
149 const std::string pixelFormatString = ::android::hardware::graphics::common::V1_2::toString(
150 static_cast<::android::hardware::graphics::common::V1_2::PixelFormat>(
151 descriptor.droid_format));
152 const std::string usageString = ::android::hardware::graphics::common::V1_2::toString<::android::hardware::graphics::common::V1_2::BufferUsage>(
153 static_cast<uint64_t>(descriptor.droid_usage));
154 ALOGE("Failed to allocate. Unsupported combination: pixel format:%s, drm format:%s, "
155 "usage:%s\n",
156 pixelFormatString.c_str(), drmFormatString.c_str(), usageString.c_str());
157 return ToBinderStatus(AllocationError::UNSUPPORTED);
158 }
159
160 native_handle_t* handle;
161 int ret = mDriver->allocate(&descriptor, &handle);
162 if (ret) {
163 return ToBinderStatus(AllocationError::NO_RESOURCES);
164 }
165
166 cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(handle);
167 *outStride = static_cast<int32_t>(crosHandle->pixel_stride);
168 *outHandle = handle;
169
170 return ndk::ScopedAStatus::ok();
171 }
172
isSupported(const BufferDescriptorInfo & descriptor,bool * outResult)173 ndk::ScopedAStatus Allocator::isSupported(const BufferDescriptorInfo& descriptor,
174 bool* outResult) {
175 if (!mDriver) {
176 ALOGE("Failed to allocate. Driver is uninitialized.\n");
177 return ToBinderStatus(AllocationError::NO_RESOURCES);
178 }
179
180 for (const auto& option : descriptor.additionalOptions) {
181 if (option.name != STANDARD_METADATA_DATASPACE) {
182 *outResult = false;
183 return ndk::ScopedAStatus::ok();
184 }
185 }
186
187 struct cros_gralloc_buffer_descriptor crosDescriptor = {};
188 ndk::ScopedAStatus status = convertToCrosDescriptor(descriptor, crosDescriptor);
189 if (!status.isOk()) {
190 // Failing to convert the descriptor means the layer count, pixel format, or usage is
191 // unsupported, thus isSupported() = false
192 *outResult = false;
193 return ndk::ScopedAStatus::ok();
194 }
195
196 *outResult = mDriver->is_supported(&crosDescriptor);
197 return ndk::ScopedAStatus::ok();
198 }
199
getIMapperLibrarySuffix(std::string * outResult)200 ndk::ScopedAStatus Allocator::getIMapperLibrarySuffix(std::string* outResult) {
201 *outResult = "minigbm";
202 return ndk::ScopedAStatus::ok();
203 }
204
createBinder()205 ::ndk::SpAIBinder Allocator::createBinder() {
206 auto binder = BnAllocator::createBinder();
207 AIBinder_setInheritRt(binder.get(), true);
208 return binder;
209 }
210
211 } // namespace aidl::android::hardware::graphics::allocator::impl