blob: e6e088826b3e22a542ccee14e11883dbf6194ce4 [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 =
127 static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::CPU_READ_OFTEN);
Brian Duddiec3253372022-06-09 12:37:53 -0700128 AllocatorWrapperT<AllocatorT> mAllocator;
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700129 sp<MapperT> mMapper;
130
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700131 // v2.0 and v3.0 use vec<uint32_t> for BufferDescriptor, but v4.0 uses vec<uint8_t>, so use
132 // some template magic to deduce the right type based off of the first argument to allocate(),
133 // which is always the version-specific BufferDescriptor type
134 typedef BaseTypeOfFirstArg<decltype(&AllocatorT::allocate)> BufferDescriptorT;
135
136 BufferDescriptorT getDescriptor(uint32_t size);
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700137 native_handle_t* importBuffer(const hidl_handle& rawHandle);
138};
139
Brian Duddiec3253372022-06-09 12:37:53 -0700140template <>
141native_handle_t* GrallocHalWrapper<IAllocatorAidl, IMapper4, std::shared_ptr>::allocate(
142 uint32_t size) {
143 constexpr uint32_t kBufferCount = 1;
144 BufferDescriptorT descriptor = getDescriptor(size);
145 native_handle_t* bufferHandle = nullptr;
146
147 AllocationResult result;
148 auto status = mAllocator->allocate(descriptor, kBufferCount, &result);
149 if (!status.isOk()) {
150 status_t error = status.getExceptionCode();
151 ALOGE("Failed to allocate buffer: %" PRId32, static_cast<int32_t>(error));
152 } else if (result.buffers.size() != kBufferCount) {
153 ALOGE("Invalid buffer array size (got %zu, expected %" PRIu32 ")", result.buffers.size(),
154 kBufferCount);
155 } else {
156 // Convert from AIDL NativeHandle to native_handle_t to hidl_handle
157 hidl_handle hidlHandle;
158 hidlHandle.setTo(dupFromAidl(result.buffers[0]), /*shouldOwn*/ true);
159 bufferHandle = importBuffer(hidlHandle);
160 }
161
162 return bufferHandle;
163}
164
165template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
166native_handle_t* GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::allocate(
167 uint32_t size) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700168 constexpr uint32_t kBufferCount = 1;
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700169 BufferDescriptorT descriptor = getDescriptor(size);
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700170 native_handle_t* bufferHandle = nullptr;
Brian Stackeb755f52018-09-26 14:53:25 -0700171
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700172 auto callback = [&](auto error, uint32_t /*stride*/, const hidl_vec<hidl_handle>& buffers) {
173 if (failed(error)) {
174 ALOGE("Failed to allocate buffer: %" PRId32, static_cast<int32_t>(error));
175 } else if (buffers.size() != kBufferCount) {
176 ALOGE("Invalid buffer array size (got %zu, expected %" PRIu32 ")", buffers.size(),
177 kBufferCount);
178 } else {
179 bufferHandle = importBuffer(buffers[0]);
180 }
181 };
182
183 mAllocator->allocate(descriptor, kBufferCount, callback);
Brian Stackeb755f52018-09-26 14:53:25 -0700184 return bufferHandle;
185}
186
Brian Duddiec3253372022-06-09 12:37:53 -0700187template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
188void GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::freeBuffer(
189 native_handle_t* bufferHandle) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700190 auto error = mMapper->freeBuffer(bufferHandle);
191 if (!error.isOk() || failed(error)) {
192 ALOGE("Failed to free buffer %p", bufferHandle);
193 }
Brian Stackeb755f52018-09-26 14:53:25 -0700194}
195
Brian Duddiec3253372022-06-09 12:37:53 -0700196template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
197typename GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::BufferDescriptorT
198GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::getDescriptor(uint32_t size) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700199 typename MapperT::BufferDescriptorInfo descriptorInfo = {
200 .width = size,
201 .height = 1,
202 .layerCount = 1,
Nick Desaulniers65d03e42019-10-28 13:44:49 -0700203 .format = static_cast<decltype(descriptorInfo.format)>(PixelFormat::BLOB),
Nick Desaulniers6f4a2322019-11-12 13:48:58 -0800204 .usage = kBufferUsage,
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700205 };
Brian Stackeb755f52018-09-26 14:53:25 -0700206
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700207 BufferDescriptorT descriptor;
208 auto callback = [&](auto error, const BufferDescriptorT& tmpDescriptor) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700209 if (failed(error)) {
210 ALOGE("Failed to create descriptor: %" PRId32, static_cast<int32_t>(error));
211 } else {
212 descriptor = tmpDescriptor;
Brian Stackeb755f52018-09-26 14:53:25 -0700213 }
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700214 };
Brian Stackeb755f52018-09-26 14:53:25 -0700215
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700216 mMapper->createDescriptor(descriptorInfo, callback);
Brian Stackeb755f52018-09-26 14:53:25 -0700217 return descriptor;
218}
219
Brian Duddiec3253372022-06-09 12:37:53 -0700220template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
221native_handle_t* GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::importBuffer(
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700222 const hidl_handle& rawHandle) {
223 native_handle_t* bufferHandle = nullptr;
Brian Stackeb755f52018-09-26 14:53:25 -0700224
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700225 mMapper->importBuffer(rawHandle, [&](auto error, void* tmpBuffer) {
226 if (failed(error)) {
227 ALOGE("Failed to import buffer %p: %" PRId32, rawHandle.getNativeHandle(),
228 static_cast<int32_t>(error));
229 } else {
230 bufferHandle = static_cast<native_handle_t*>(tmpBuffer);
231 }
232 });
Brian Stackeb755f52018-09-26 14:53:25 -0700233
234 return bufferHandle;
235}
236
Brian Duddiec3253372022-06-09 12:37:53 -0700237template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
238void* GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::lock(
239 native_handle_t* bufferHandle) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700240 // Per the HAL, all-zeros Rect means the entire buffer
241 typename MapperT::Rect accessRegion = {};
242 hidl_handle acquireFenceHandle; // No fence needed, already safe to lock
Brian Stackeb755f52018-09-26 14:53:25 -0700243
244 void* data = nullptr;
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700245 mMapper->lock(bufferHandle, kBufferUsage, accessRegion, acquireFenceHandle,
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700246 [&](auto error, void* tmpData, ...) { // V3/4 pass extra args we don't use
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700247 if (failed(error)) {
248 ALOGE("Failed to lock buffer %p: %" PRId32, bufferHandle,
249 static_cast<int32_t>(error));
250 } else {
251 data = tmpData;
Brian Stackeb755f52018-09-26 14:53:25 -0700252 }
Brian Stackeb755f52018-09-26 14:53:25 -0700253 });
254
Brian Stackeb755f52018-09-26 14:53:25 -0700255 return data;
256}
257
Brian Duddiec3253372022-06-09 12:37:53 -0700258template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
259void GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::unlock(
260 native_handle_t* bufferHandle) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700261 mMapper->unlock(bufferHandle, [&](auto error, const hidl_handle& /*releaseFence*/) {
262 if (failed(error)) {
263 ALOGE("Failed to unlock buffer %p: %" PRId32, bufferHandle,
264 static_cast<int32_t>(error));
Brian Stackeb755f52018-09-26 14:53:25 -0700265 }
266 });
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700267}
Brian Stackeb755f52018-09-26 14:53:25 -0700268
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700269} // anonymous namespace
270
271GrallocWrapper::GrallocWrapper() {
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700272 sp<IAllocator4> allocator4 = IAllocator4::getService();
273 sp<IMapper4> mapper4 = IMapper4::getService();
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700274
Brian Duddiec3253372022-06-09 12:37:53 -0700275 const auto kAllocatorSvc = std::string(IAllocatorAidl::descriptor) + "/default";
276 std::shared_ptr<IAllocatorAidl> allocatorAidl;
277 if (AServiceManager_isDeclared(kAllocatorSvc.c_str())) {
278 allocatorAidl = IAllocatorAidl::fromBinder(
279 ndk::SpAIBinder(AServiceManager_checkService(kAllocatorSvc.c_str())));
280 }
281
282 // As of T, AIDL Allocator is supported only with HIDL Mapper4
283 // (ref: VtsHalGraphicsAllocatorAidl_TargetTest.cpp)
284 if (allocatorAidl != nullptr && mapper4 != nullptr) {
285 ALOGD("Using AIDL IAllocator + HIDL IMapper v4.0");
286 mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
287 new GrallocHalWrapper<IAllocatorAidl, IMapper4, std::shared_ptr>(allocatorAidl,
288 mapper4));
289 } else if (allocator4 != nullptr && mapper4 != nullptr) {
290 ALOGD("AIDL IAllocator not found, using HIDL IAllocator/IMapper v4.0");
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700291 mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700292 new GrallocHalWrapper<IAllocator4, IMapper4>(allocator4, mapper4));
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700293 } else {
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700294 ALOGD("Graphics HALs 4.0 not found (allocator %d mapper %d), falling back to 3.0",
295 (allocator4 != nullptr), (mapper4 != nullptr));
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700296
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700297 sp<IAllocator3> allocator3 = IAllocator3::getService();
298 sp<IMapper3> mapper3 = IMapper3::getService();
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700299
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700300 if (allocator3 != nullptr && mapper3 != nullptr) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700301 mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700302 new GrallocHalWrapper<IAllocator3, IMapper3>(allocator3, mapper3));
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700303 } else {
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700304 ALOGD("Graphics HALs 3.0 not found (allocator %d mapper %d), falling back to 2.x",
305 (allocator3 != nullptr), (mapper3 != nullptr));
306
307 sp<IAllocator2> allocator2 = IAllocator2::getService();
308 sp<IMapper2> mapper2 = IMapper2_1::getService();
309 if (mapper2 == nullptr) {
310 mapper2 = IMapper2::getService();
311 }
312
313 if (allocator2 != nullptr && mapper2 != nullptr) {
314 mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
315 new GrallocHalWrapper<IAllocator2, IMapper2>(allocator2, mapper2));
316 } else {
317 ALOGE("Couldn't open graphics HALs (2.x allocator %d mapper %d)",
318 (allocator2 != nullptr), (mapper2 != nullptr));
319 }
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700320 }
321 }
322}
323
324GrallocWrapper::~GrallocWrapper() {
325 for (auto bufferHandle : mAllocatedBuffers) {
326 mGrallocHal->unlock(bufferHandle);
327 mGrallocHal->freeBuffer(bufferHandle);
328 }
329 mAllocatedBuffers.clear();
330}
331
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700332std::pair<native_handle_t*, void*> GrallocWrapper::allocate(uint32_t size) {
333 native_handle_t* bufferHandle = mGrallocHal->allocate(size);
334 void* buffer = nullptr;
335 if (bufferHandle) {
336 buffer = mGrallocHal->lock(bufferHandle);
337 if (buffer) {
338 mAllocatedBuffers.insert(bufferHandle);
339 } else {
340 mGrallocHal->freeBuffer(bufferHandle);
341 bufferHandle = nullptr;
342 }
343 }
344 return std::make_pair<>(bufferHandle, buffer);
345}
346
347void GrallocWrapper::freeBuffer(native_handle_t* bufferHandle) {
348 if (mAllocatedBuffers.erase(bufferHandle)) {
349 mGrallocHal->unlock(bufferHandle);
350 mGrallocHal->freeBuffer(bufferHandle);
351 }
Brian Stackeb755f52018-09-26 14:53:25 -0700352}
353
354} // namespace android