blob: a15e7fee8c0f29a2edd9a39d2725801416cf8525 [file] [log] [blame]
Brian Stackeb755f52018-09-26 14:53:25 -07001/*
2 * Copyright (C) 2017 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
Brian Stackeb755f52018-09-26 14:53:25 -070017#include "GrallocWrapper.h"
18
Brian Duddiec3253372022-06-09 12:37:53 -070019#include <aidl/android/hardware/graphics/allocator/IAllocator.h>
20#include <aidlcommonsupport/NativeHandle.h>
21#include <android/binder_manager.h>
Brian Duddiedf6e2b72019-08-01 19:18:06 -070022#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
23#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
Brian Duddie97f1a3a2020-06-04 14:42:46 -070024#include <android/hardware/graphics/allocator/4.0/IAllocator.h>
Brian Duddiedf6e2b72019-08-01 19:18:06 -070025#include <android/hardware/graphics/mapper/2.0/IMapper.h>
26#include <android/hardware/graphics/mapper/2.1/IMapper.h>
27#include <android/hardware/graphics/mapper/3.0/IMapper.h>
Brian Duddie97f1a3a2020-06-04 14:42:46 -070028#include <android/hardware/graphics/mapper/4.0/IMapper.h>
Brian Duddiedf6e2b72019-08-01 19:18:06 -070029
Brian Stackeb755f52018-09-26 14:53:25 -070030#include <utils/Log.h>
31
Brian Duddiedf6e2b72019-08-01 19:18:06 -070032#include <cinttypes>
Brian Duddiec3253372022-06-09 12:37:53 -070033#include <memory>
Brian Duddiedf6e2b72019-08-01 19:18:06 -070034#include <type_traits>
35
Brian Duddiec3253372022-06-09 12:37:53 -070036using IAllocatorAidl = ::aidl::android::hardware::graphics::allocator::IAllocator;
Brian Duddiedf6e2b72019-08-01 19:18:06 -070037using IAllocator2 = ::android::hardware::graphics::allocator::V2_0::IAllocator;
38using IAllocator3 = ::android::hardware::graphics::allocator::V3_0::IAllocator;
Brian Duddie97f1a3a2020-06-04 14:42:46 -070039using IAllocator4 = ::android::hardware::graphics::allocator::V4_0::IAllocator;
Brian Duddiedf6e2b72019-08-01 19:18:06 -070040using IMapper2 = ::android::hardware::graphics::mapper::V2_0::IMapper;
41using IMapper2_1 = ::android::hardware::graphics::mapper::V2_1::IMapper;
42using IMapper3 = ::android::hardware::graphics::mapper::V3_0::IMapper;
Brian Duddie97f1a3a2020-06-04 14:42:46 -070043using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
Brian Duddiedf6e2b72019-08-01 19:18:06 -070044
45using Error2 = ::android::hardware::graphics::mapper::V2_0::Error;
46using Error3 = ::android::hardware::graphics::mapper::V3_0::Error;
Brian Duddie97f1a3a2020-06-04 14:42:46 -070047using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
Brian Duddiedf6e2b72019-08-01 19:18:06 -070048
Brian Duddiec3253372022-06-09 12:37:53 -070049using ::aidl::android::hardware::common::NativeHandle;
50using ::aidl::android::hardware::graphics::allocator::AllocationResult;
51
Brian Duddiedf6e2b72019-08-01 19:18:06 -070052using ::android::hardware::graphics::common::V1_0::BufferUsage;
53using ::android::hardware::graphics::common::V1_0::PixelFormat;
54
Brian Duddiedf6e2b72019-08-01 19:18:06 -070055using ::android::hardware::hidl_handle;
56using ::android::hardware::hidl_string;
57using ::android::hardware::hidl_vec;
58
Brian Stackeb755f52018-09-26 14:53:25 -070059namespace android {
60
Brian Duddiedf6e2b72019-08-01 19:18:06 -070061// Since we use the same APIs across allocator/mapper HALs but they have major
62// version differences (meaning they are not related through inheritance), we
63// create a common interface abstraction for the IAllocator + IMapper combination
64// (major versions need to match in the current HALs, e.g. IAllocator 3.0 needs to
65// be paired with IMapper 3.0, so these are tied together)
66class IGrallocHalWrapper {
67 public:
68 virtual ~IGrallocHalWrapper() = default;
69
70 // IAllocator
Brian Duddiedf6e2b72019-08-01 19:18:06 -070071 virtual native_handle_t* allocate(uint32_t size) = 0;
72 virtual void freeBuffer(native_handle_t* bufferHandle) = 0;
73
74 // IMapper
75 virtual void* lock(native_handle_t* bufferHandle) = 0;
76 virtual void unlock(native_handle_t* bufferHandle) = 0;
77};
78
79namespace {
80
81bool failed(Error2 error) {
82 return (error != Error2::NONE);
83}
84bool failed(Error3 error) {
85 return (error != Error3::NONE);
Brian Stackeb755f52018-09-26 14:53:25 -070086}
Brian Duddie97f1a3a2020-06-04 14:42:46 -070087bool failed(Error4 error) {
88 return (error != Error4::NONE);
89}
90
91template <typename>
92struct FirstArg;
93
94// Template specialization for pointer to a non-static member function, which exposes
95// the type of the first argument given to said function
96template <typename ReturnType, typename ClassT, typename Arg1, typename... OtherArgs>
97struct FirstArg<ReturnType (ClassT::*)(Arg1, OtherArgs...)> {
98 using type = Arg1;
99};
100
101// Alias to FirstArg which also removes any reference type and const associated
102template <typename T>
103using BaseTypeOfFirstArg = typename std::remove_const<
104 typename std::remove_reference<typename FirstArg<T>::type>::type>::type;
Brian Stackeb755f52018-09-26 14:53:25 -0700105
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700106// Since all the type and function names are the same for the things we use across the major HAL
107// versions, we use template magic to avoid repeating ourselves.
Brian Duddiec3253372022-06-09 12:37:53 -0700108template <typename AllocatorT, typename MapperT,
109 template <typename> typename AllocatorWrapperT = sp>
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700110class GrallocHalWrapper : public IGrallocHalWrapper {
111 public:
Brian Duddiec3253372022-06-09 12:37:53 -0700112 GrallocHalWrapper(const AllocatorWrapperT<AllocatorT>& allocator, const sp<MapperT>& mapper)
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700113 : mAllocator(allocator), mMapper(mapper) {
114 if (mapper->isRemote()) {
115 ALOGE("Mapper is in passthrough mode");
Brian Stackeb755f52018-09-26 14:53:25 -0700116 }
117 }
Brian Stackeb755f52018-09-26 14:53:25 -0700118
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700119 virtual native_handle_t* allocate(uint32_t size) override;
120 virtual void freeBuffer(native_handle_t* bufferHandle) override;
Brian Stackeb755f52018-09-26 14:53:25 -0700121
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700122 virtual void* lock(native_handle_t* bufferHandle) override;
123 virtual void unlock(native_handle_t* bufferHandle) override;
124
125 private:
126 static constexpr uint64_t kBufferUsage =
Arthur Ishiguro802c53d2023-08-09 18:17:23 +0000127 static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::CPU_READ_OFTEN |
128 BufferUsage::CPU_WRITE_RARELY);
Brian Duddiec3253372022-06-09 12:37:53 -0700129 AllocatorWrapperT<AllocatorT> mAllocator;
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700130 sp<MapperT> mMapper;
131
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700132 // v2.0 and v3.0 use vec<uint32_t> for BufferDescriptor, but v4.0 uses vec<uint8_t>, so use
133 // some template magic to deduce the right type based off of the first argument to allocate(),
134 // which is always the version-specific BufferDescriptor type
135 typedef BaseTypeOfFirstArg<decltype(&AllocatorT::allocate)> BufferDescriptorT;
136
137 BufferDescriptorT getDescriptor(uint32_t size);
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700138 native_handle_t* importBuffer(const hidl_handle& rawHandle);
139};
140
Brian Duddiec3253372022-06-09 12:37:53 -0700141template <>
142native_handle_t* GrallocHalWrapper<IAllocatorAidl, IMapper4, std::shared_ptr>::allocate(
143 uint32_t size) {
144 constexpr uint32_t kBufferCount = 1;
145 BufferDescriptorT descriptor = getDescriptor(size);
146 native_handle_t* bufferHandle = nullptr;
147
148 AllocationResult result;
149 auto status = mAllocator->allocate(descriptor, kBufferCount, &result);
150 if (!status.isOk()) {
151 status_t error = status.getExceptionCode();
152 ALOGE("Failed to allocate buffer: %" PRId32, static_cast<int32_t>(error));
153 } else if (result.buffers.size() != kBufferCount) {
154 ALOGE("Invalid buffer array size (got %zu, expected %" PRIu32 ")", result.buffers.size(),
155 kBufferCount);
156 } else {
157 // Convert from AIDL NativeHandle to native_handle_t to hidl_handle
158 hidl_handle hidlHandle;
159 hidlHandle.setTo(dupFromAidl(result.buffers[0]), /*shouldOwn*/ true);
160 bufferHandle = importBuffer(hidlHandle);
161 }
162
163 return bufferHandle;
164}
165
166template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
167native_handle_t* GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::allocate(
168 uint32_t size) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700169 constexpr uint32_t kBufferCount = 1;
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700170 BufferDescriptorT descriptor = getDescriptor(size);
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700171 native_handle_t* bufferHandle = nullptr;
Brian Stackeb755f52018-09-26 14:53:25 -0700172
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700173 auto callback = [&](auto error, uint32_t /*stride*/, const hidl_vec<hidl_handle>& buffers) {
174 if (failed(error)) {
175 ALOGE("Failed to allocate buffer: %" PRId32, static_cast<int32_t>(error));
176 } else if (buffers.size() != kBufferCount) {
177 ALOGE("Invalid buffer array size (got %zu, expected %" PRIu32 ")", buffers.size(),
178 kBufferCount);
179 } else {
180 bufferHandle = importBuffer(buffers[0]);
181 }
182 };
183
184 mAllocator->allocate(descriptor, kBufferCount, callback);
Brian Stackeb755f52018-09-26 14:53:25 -0700185 return bufferHandle;
186}
187
Brian Duddiec3253372022-06-09 12:37:53 -0700188template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
189void GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::freeBuffer(
190 native_handle_t* bufferHandle) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700191 auto error = mMapper->freeBuffer(bufferHandle);
192 if (!error.isOk() || failed(error)) {
193 ALOGE("Failed to free buffer %p", bufferHandle);
194 }
Brian Stackeb755f52018-09-26 14:53:25 -0700195}
196
Brian Duddiec3253372022-06-09 12:37:53 -0700197template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
198typename GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::BufferDescriptorT
199GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::getDescriptor(uint32_t size) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700200 typename MapperT::BufferDescriptorInfo descriptorInfo = {
201 .width = size,
202 .height = 1,
203 .layerCount = 1,
Nick Desaulniers65d03e42019-10-28 13:44:49 -0700204 .format = static_cast<decltype(descriptorInfo.format)>(PixelFormat::BLOB),
Nick Desaulniers6f4a2322019-11-12 13:48:58 -0800205 .usage = kBufferUsage,
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700206 };
Brian Stackeb755f52018-09-26 14:53:25 -0700207
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700208 BufferDescriptorT descriptor;
209 auto callback = [&](auto error, const BufferDescriptorT& tmpDescriptor) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700210 if (failed(error)) {
211 ALOGE("Failed to create descriptor: %" PRId32, static_cast<int32_t>(error));
212 } else {
213 descriptor = tmpDescriptor;
Brian Stackeb755f52018-09-26 14:53:25 -0700214 }
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700215 };
Brian Stackeb755f52018-09-26 14:53:25 -0700216
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700217 mMapper->createDescriptor(descriptorInfo, callback);
Brian Stackeb755f52018-09-26 14:53:25 -0700218 return descriptor;
219}
220
Brian Duddiec3253372022-06-09 12:37:53 -0700221template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
222native_handle_t* GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::importBuffer(
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700223 const hidl_handle& rawHandle) {
224 native_handle_t* bufferHandle = nullptr;
Brian Stackeb755f52018-09-26 14:53:25 -0700225
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700226 mMapper->importBuffer(rawHandle, [&](auto error, void* tmpBuffer) {
227 if (failed(error)) {
228 ALOGE("Failed to import buffer %p: %" PRId32, rawHandle.getNativeHandle(),
229 static_cast<int32_t>(error));
230 } else {
231 bufferHandle = static_cast<native_handle_t*>(tmpBuffer);
232 }
233 });
Brian Stackeb755f52018-09-26 14:53:25 -0700234
235 return bufferHandle;
236}
237
Brian Duddiec3253372022-06-09 12:37:53 -0700238template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
239void* GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::lock(
240 native_handle_t* bufferHandle) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700241 // Per the HAL, all-zeros Rect means the entire buffer
242 typename MapperT::Rect accessRegion = {};
243 hidl_handle acquireFenceHandle; // No fence needed, already safe to lock
Brian Stackeb755f52018-09-26 14:53:25 -0700244
245 void* data = nullptr;
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700246 mMapper->lock(bufferHandle, kBufferUsage, accessRegion, acquireFenceHandle,
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700247 [&](auto error, void* tmpData, ...) { // V3/4 pass extra args we don't use
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700248 if (failed(error)) {
249 ALOGE("Failed to lock buffer %p: %" PRId32, bufferHandle,
250 static_cast<int32_t>(error));
251 } else {
252 data = tmpData;
Brian Stackeb755f52018-09-26 14:53:25 -0700253 }
Brian Stackeb755f52018-09-26 14:53:25 -0700254 });
255
Brian Stackeb755f52018-09-26 14:53:25 -0700256 return data;
257}
258
Brian Duddiec3253372022-06-09 12:37:53 -0700259template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
260void GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::unlock(
261 native_handle_t* bufferHandle) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700262 mMapper->unlock(bufferHandle, [&](auto error, const hidl_handle& /*releaseFence*/) {
263 if (failed(error)) {
264 ALOGE("Failed to unlock buffer %p: %" PRId32, bufferHandle,
265 static_cast<int32_t>(error));
Brian Stackeb755f52018-09-26 14:53:25 -0700266 }
267 });
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700268}
Brian Stackeb755f52018-09-26 14:53:25 -0700269
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700270} // anonymous namespace
271
272GrallocWrapper::GrallocWrapper() {
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700273 sp<IAllocator4> allocator4 = IAllocator4::getService();
274 sp<IMapper4> mapper4 = IMapper4::getService();
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700275
Brian Duddiec3253372022-06-09 12:37:53 -0700276 const auto kAllocatorSvc = std::string(IAllocatorAidl::descriptor) + "/default";
277 std::shared_ptr<IAllocatorAidl> allocatorAidl;
278 if (AServiceManager_isDeclared(kAllocatorSvc.c_str())) {
279 allocatorAidl = IAllocatorAidl::fromBinder(
280 ndk::SpAIBinder(AServiceManager_checkService(kAllocatorSvc.c_str())));
281 }
282
283 // As of T, AIDL Allocator is supported only with HIDL Mapper4
284 // (ref: VtsHalGraphicsAllocatorAidl_TargetTest.cpp)
285 if (allocatorAidl != nullptr && mapper4 != nullptr) {
286 ALOGD("Using AIDL IAllocator + HIDL IMapper v4.0");
287 mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
288 new GrallocHalWrapper<IAllocatorAidl, IMapper4, std::shared_ptr>(allocatorAidl,
289 mapper4));
290 } else if (allocator4 != nullptr && mapper4 != nullptr) {
291 ALOGD("AIDL IAllocator not found, using HIDL IAllocator/IMapper v4.0");
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700292 mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700293 new GrallocHalWrapper<IAllocator4, IMapper4>(allocator4, mapper4));
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700294 } else {
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700295 ALOGD("Graphics HALs 4.0 not found (allocator %d mapper %d), falling back to 3.0",
296 (allocator4 != nullptr), (mapper4 != nullptr));
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700297
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700298 sp<IAllocator3> allocator3 = IAllocator3::getService();
299 sp<IMapper3> mapper3 = IMapper3::getService();
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700300
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700301 if (allocator3 != nullptr && mapper3 != nullptr) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700302 mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700303 new GrallocHalWrapper<IAllocator3, IMapper3>(allocator3, mapper3));
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700304 } else {
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700305 ALOGD("Graphics HALs 3.0 not found (allocator %d mapper %d), falling back to 2.x",
306 (allocator3 != nullptr), (mapper3 != nullptr));
307
308 sp<IAllocator2> allocator2 = IAllocator2::getService();
309 sp<IMapper2> mapper2 = IMapper2_1::getService();
310 if (mapper2 == nullptr) {
311 mapper2 = IMapper2::getService();
312 }
313
314 if (allocator2 != nullptr && mapper2 != nullptr) {
315 mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
316 new GrallocHalWrapper<IAllocator2, IMapper2>(allocator2, mapper2));
317 } else {
318 ALOGE("Couldn't open graphics HALs (2.x allocator %d mapper %d)",
319 (allocator2 != nullptr), (mapper2 != nullptr));
320 }
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700321 }
322 }
323}
324
325GrallocWrapper::~GrallocWrapper() {
326 for (auto bufferHandle : mAllocatedBuffers) {
327 mGrallocHal->unlock(bufferHandle);
328 mGrallocHal->freeBuffer(bufferHandle);
329 }
330 mAllocatedBuffers.clear();
331}
332
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700333std::pair<native_handle_t*, void*> GrallocWrapper::allocate(uint32_t size) {
334 native_handle_t* bufferHandle = mGrallocHal->allocate(size);
335 void* buffer = nullptr;
336 if (bufferHandle) {
337 buffer = mGrallocHal->lock(bufferHandle);
338 if (buffer) {
339 mAllocatedBuffers.insert(bufferHandle);
340 } else {
341 mGrallocHal->freeBuffer(bufferHandle);
342 bufferHandle = nullptr;
343 }
344 }
345 return std::make_pair<>(bufferHandle, buffer);
346}
347
348void GrallocWrapper::freeBuffer(native_handle_t* bufferHandle) {
349 if (mAllocatedBuffers.erase(bufferHandle)) {
350 mGrallocHal->unlock(bufferHandle);
351 mGrallocHal->freeBuffer(bufferHandle);
352 }
Brian Stackeb755f52018-09-26 14:53:25 -0700353}
354
355} // namespace android