blob: 47d1f4215271dda1ec501961b763413d50f211ce [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 Duddiedf6e2b72019-08-01 19:18:06 -070019#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
20#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
Brian Duddie97f1a3a2020-06-04 14:42:46 -070021#include <android/hardware/graphics/allocator/4.0/IAllocator.h>
Brian Duddiedf6e2b72019-08-01 19:18:06 -070022#include <android/hardware/graphics/mapper/2.0/IMapper.h>
23#include <android/hardware/graphics/mapper/2.1/IMapper.h>
24#include <android/hardware/graphics/mapper/3.0/IMapper.h>
Brian Duddie97f1a3a2020-06-04 14:42:46 -070025#include <android/hardware/graphics/mapper/4.0/IMapper.h>
Brian Duddiedf6e2b72019-08-01 19:18:06 -070026
Brian Stackeb755f52018-09-26 14:53:25 -070027#include <utils/Log.h>
28
Brian Duddiedf6e2b72019-08-01 19:18:06 -070029#include <cinttypes>
30#include <type_traits>
31
32using IAllocator2 = ::android::hardware::graphics::allocator::V2_0::IAllocator;
33using IAllocator3 = ::android::hardware::graphics::allocator::V3_0::IAllocator;
Brian Duddie97f1a3a2020-06-04 14:42:46 -070034using IAllocator4 = ::android::hardware::graphics::allocator::V4_0::IAllocator;
Brian Duddiedf6e2b72019-08-01 19:18:06 -070035using IMapper2 = ::android::hardware::graphics::mapper::V2_0::IMapper;
36using IMapper2_1 = ::android::hardware::graphics::mapper::V2_1::IMapper;
37using IMapper3 = ::android::hardware::graphics::mapper::V3_0::IMapper;
Brian Duddie97f1a3a2020-06-04 14:42:46 -070038using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
Brian Duddiedf6e2b72019-08-01 19:18:06 -070039
40using Error2 = ::android::hardware::graphics::mapper::V2_0::Error;
41using Error3 = ::android::hardware::graphics::mapper::V3_0::Error;
Brian Duddie97f1a3a2020-06-04 14:42:46 -070042using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
Brian Duddiedf6e2b72019-08-01 19:18:06 -070043
44using ::android::hardware::graphics::common::V1_0::BufferUsage;
45using ::android::hardware::graphics::common::V1_0::PixelFormat;
46
Brian Duddiedf6e2b72019-08-01 19:18:06 -070047using ::android::hardware::hidl_handle;
48using ::android::hardware::hidl_string;
49using ::android::hardware::hidl_vec;
50
Brian Stackeb755f52018-09-26 14:53:25 -070051namespace android {
52
Brian Duddiedf6e2b72019-08-01 19:18:06 -070053// Since we use the same APIs across allocator/mapper HALs but they have major
54// version differences (meaning they are not related through inheritance), we
55// create a common interface abstraction for the IAllocator + IMapper combination
56// (major versions need to match in the current HALs, e.g. IAllocator 3.0 needs to
57// be paired with IMapper 3.0, so these are tied together)
58class IGrallocHalWrapper {
59 public:
60 virtual ~IGrallocHalWrapper() = default;
61
62 // IAllocator
Brian Duddiedf6e2b72019-08-01 19:18:06 -070063 virtual native_handle_t* allocate(uint32_t size) = 0;
64 virtual void freeBuffer(native_handle_t* bufferHandle) = 0;
65
66 // IMapper
67 virtual void* lock(native_handle_t* bufferHandle) = 0;
68 virtual void unlock(native_handle_t* bufferHandle) = 0;
69};
70
71namespace {
72
73bool failed(Error2 error) {
74 return (error != Error2::NONE);
75}
76bool failed(Error3 error) {
77 return (error != Error3::NONE);
Brian Stackeb755f52018-09-26 14:53:25 -070078}
Brian Duddie97f1a3a2020-06-04 14:42:46 -070079bool failed(Error4 error) {
80 return (error != Error4::NONE);
81}
82
83template <typename>
84struct FirstArg;
85
86// Template specialization for pointer to a non-static member function, which exposes
87// the type of the first argument given to said function
88template <typename ReturnType, typename ClassT, typename Arg1, typename... OtherArgs>
89struct FirstArg<ReturnType (ClassT::*)(Arg1, OtherArgs...)> {
90 using type = Arg1;
91};
92
93// Alias to FirstArg which also removes any reference type and const associated
94template <typename T>
95using BaseTypeOfFirstArg = typename std::remove_const<
96 typename std::remove_reference<typename FirstArg<T>::type>::type>::type;
Brian Stackeb755f52018-09-26 14:53:25 -070097
Brian Duddiedf6e2b72019-08-01 19:18:06 -070098// Since all the type and function names are the same for the things we use across the major HAL
99// versions, we use template magic to avoid repeating ourselves.
100template <typename AllocatorT, typename MapperT>
101class GrallocHalWrapper : public IGrallocHalWrapper {
102 public:
103 GrallocHalWrapper(const sp<AllocatorT>& allocator, const sp<MapperT>& mapper)
104 : mAllocator(allocator), mMapper(mapper) {
105 if (mapper->isRemote()) {
106 ALOGE("Mapper is in passthrough mode");
Brian Stackeb755f52018-09-26 14:53:25 -0700107 }
108 }
Brian Stackeb755f52018-09-26 14:53:25 -0700109
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700110 virtual native_handle_t* allocate(uint32_t size) override;
111 virtual void freeBuffer(native_handle_t* bufferHandle) override;
Brian Stackeb755f52018-09-26 14:53:25 -0700112
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700113 virtual void* lock(native_handle_t* bufferHandle) override;
114 virtual void unlock(native_handle_t* bufferHandle) override;
115
116 private:
117 static constexpr uint64_t kBufferUsage =
118 static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::CPU_READ_OFTEN);
119 sp<AllocatorT> mAllocator;
120 sp<MapperT> mMapper;
121
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700122 // v2.0 and v3.0 use vec<uint32_t> for BufferDescriptor, but v4.0 uses vec<uint8_t>, so use
123 // some template magic to deduce the right type based off of the first argument to allocate(),
124 // which is always the version-specific BufferDescriptor type
125 typedef BaseTypeOfFirstArg<decltype(&AllocatorT::allocate)> BufferDescriptorT;
126
127 BufferDescriptorT getDescriptor(uint32_t size);
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700128 native_handle_t* importBuffer(const hidl_handle& rawHandle);
129};
130
131template <typename AllocatorT, typename MapperT>
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700132native_handle_t* GrallocHalWrapper<AllocatorT, MapperT>::allocate(uint32_t size) {
133 constexpr uint32_t kBufferCount = 1;
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700134 BufferDescriptorT descriptor = getDescriptor(size);
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700135 native_handle_t* bufferHandle = nullptr;
Brian Stackeb755f52018-09-26 14:53:25 -0700136
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700137 auto callback = [&](auto error, uint32_t /*stride*/, const hidl_vec<hidl_handle>& buffers) {
138 if (failed(error)) {
139 ALOGE("Failed to allocate buffer: %" PRId32, static_cast<int32_t>(error));
140 } else if (buffers.size() != kBufferCount) {
141 ALOGE("Invalid buffer array size (got %zu, expected %" PRIu32 ")", buffers.size(),
142 kBufferCount);
143 } else {
144 bufferHandle = importBuffer(buffers[0]);
145 }
146 };
147
148 mAllocator->allocate(descriptor, kBufferCount, callback);
Brian Stackeb755f52018-09-26 14:53:25 -0700149 return bufferHandle;
150}
151
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700152template <typename AllocatorT, typename MapperT>
153void GrallocHalWrapper<AllocatorT, MapperT>::freeBuffer(native_handle_t* bufferHandle) {
154 auto error = mMapper->freeBuffer(bufferHandle);
155 if (!error.isOk() || failed(error)) {
156 ALOGE("Failed to free buffer %p", bufferHandle);
157 }
Brian Stackeb755f52018-09-26 14:53:25 -0700158}
159
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700160template <typename AllocatorT, typename MapperT>
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700161typename GrallocHalWrapper<AllocatorT, MapperT>::BufferDescriptorT
162GrallocHalWrapper<AllocatorT, MapperT>::getDescriptor(uint32_t size) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700163 typename MapperT::BufferDescriptorInfo descriptorInfo = {
164 .width = size,
165 .height = 1,
166 .layerCount = 1,
Nick Desaulniers65d03e42019-10-28 13:44:49 -0700167 .format = static_cast<decltype(descriptorInfo.format)>(PixelFormat::BLOB),
Nick Desaulniers6f4a2322019-11-12 13:48:58 -0800168 .usage = kBufferUsage,
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700169 };
Brian Stackeb755f52018-09-26 14:53:25 -0700170
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700171 BufferDescriptorT descriptor;
172 auto callback = [&](auto error, const BufferDescriptorT& tmpDescriptor) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700173 if (failed(error)) {
174 ALOGE("Failed to create descriptor: %" PRId32, static_cast<int32_t>(error));
175 } else {
176 descriptor = tmpDescriptor;
Brian Stackeb755f52018-09-26 14:53:25 -0700177 }
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700178 };
Brian Stackeb755f52018-09-26 14:53:25 -0700179
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700180 mMapper->createDescriptor(descriptorInfo, callback);
Brian Stackeb755f52018-09-26 14:53:25 -0700181 return descriptor;
182}
183
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700184template <typename AllocatorT, typename MapperT>
185native_handle_t* GrallocHalWrapper<AllocatorT, MapperT>::importBuffer(
186 const hidl_handle& rawHandle) {
187 native_handle_t* bufferHandle = nullptr;
Brian Stackeb755f52018-09-26 14:53:25 -0700188
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700189 mMapper->importBuffer(rawHandle, [&](auto error, void* tmpBuffer) {
190 if (failed(error)) {
191 ALOGE("Failed to import buffer %p: %" PRId32, rawHandle.getNativeHandle(),
192 static_cast<int32_t>(error));
193 } else {
194 bufferHandle = static_cast<native_handle_t*>(tmpBuffer);
195 }
196 });
Brian Stackeb755f52018-09-26 14:53:25 -0700197
198 return bufferHandle;
199}
200
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700201template <typename AllocatorT, typename MapperT>
202void* GrallocHalWrapper<AllocatorT, MapperT>::lock(native_handle_t* bufferHandle) {
203 // Per the HAL, all-zeros Rect means the entire buffer
204 typename MapperT::Rect accessRegion = {};
205 hidl_handle acquireFenceHandle; // No fence needed, already safe to lock
Brian Stackeb755f52018-09-26 14:53:25 -0700206
207 void* data = nullptr;
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700208 mMapper->lock(bufferHandle, kBufferUsage, accessRegion, acquireFenceHandle,
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700209 [&](auto error, void* tmpData, ...) { // V3/4 pass extra args we don't use
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700210 if (failed(error)) {
211 ALOGE("Failed to lock buffer %p: %" PRId32, bufferHandle,
212 static_cast<int32_t>(error));
213 } else {
214 data = tmpData;
Brian Stackeb755f52018-09-26 14:53:25 -0700215 }
Brian Stackeb755f52018-09-26 14:53:25 -0700216 });
217
Brian Stackeb755f52018-09-26 14:53:25 -0700218 return data;
219}
220
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700221template <typename AllocatorT, typename MapperT>
222void GrallocHalWrapper<AllocatorT, MapperT>::unlock(native_handle_t* bufferHandle) {
223 mMapper->unlock(bufferHandle, [&](auto error, const hidl_handle& /*releaseFence*/) {
224 if (failed(error)) {
225 ALOGE("Failed to unlock buffer %p: %" PRId32, bufferHandle,
226 static_cast<int32_t>(error));
Brian Stackeb755f52018-09-26 14:53:25 -0700227 }
228 });
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700229}
Brian Stackeb755f52018-09-26 14:53:25 -0700230
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700231} // anonymous namespace
232
233GrallocWrapper::GrallocWrapper() {
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700234 sp<IAllocator4> allocator4 = IAllocator4::getService();
235 sp<IMapper4> mapper4 = IMapper4::getService();
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700236
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700237 if (allocator4 != nullptr && mapper4 != nullptr) {
238 ALOGD("Using IAllocator/IMapper v4.0");
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700239 mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700240 new GrallocHalWrapper<IAllocator4, IMapper4>(allocator4, mapper4));
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700241 } else {
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700242 ALOGD("Graphics HALs 4.0 not found (allocator %d mapper %d), falling back to 3.0",
243 (allocator4 != nullptr), (mapper4 != nullptr));
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700244
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700245 sp<IAllocator3> allocator3 = IAllocator3::getService();
246 sp<IMapper3> mapper3 = IMapper3::getService();
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700247
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700248 if (allocator3 != nullptr && mapper3 != nullptr) {
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700249 mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700250 new GrallocHalWrapper<IAllocator3, IMapper3>(allocator3, mapper3));
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700251 } else {
Brian Duddie97f1a3a2020-06-04 14:42:46 -0700252 ALOGD("Graphics HALs 3.0 not found (allocator %d mapper %d), falling back to 2.x",
253 (allocator3 != nullptr), (mapper3 != nullptr));
254
255 sp<IAllocator2> allocator2 = IAllocator2::getService();
256 sp<IMapper2> mapper2 = IMapper2_1::getService();
257 if (mapper2 == nullptr) {
258 mapper2 = IMapper2::getService();
259 }
260
261 if (allocator2 != nullptr && mapper2 != nullptr) {
262 mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
263 new GrallocHalWrapper<IAllocator2, IMapper2>(allocator2, mapper2));
264 } else {
265 ALOGE("Couldn't open graphics HALs (2.x allocator %d mapper %d)",
266 (allocator2 != nullptr), (mapper2 != nullptr));
267 }
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700268 }
269 }
270}
271
272GrallocWrapper::~GrallocWrapper() {
273 for (auto bufferHandle : mAllocatedBuffers) {
274 mGrallocHal->unlock(bufferHandle);
275 mGrallocHal->freeBuffer(bufferHandle);
276 }
277 mAllocatedBuffers.clear();
278}
279
Brian Duddiedf6e2b72019-08-01 19:18:06 -0700280std::pair<native_handle_t*, void*> GrallocWrapper::allocate(uint32_t size) {
281 native_handle_t* bufferHandle = mGrallocHal->allocate(size);
282 void* buffer = nullptr;
283 if (bufferHandle) {
284 buffer = mGrallocHal->lock(bufferHandle);
285 if (buffer) {
286 mAllocatedBuffers.insert(bufferHandle);
287 } else {
288 mGrallocHal->freeBuffer(bufferHandle);
289 bufferHandle = nullptr;
290 }
291 }
292 return std::make_pair<>(bufferHandle, buffer);
293}
294
295void GrallocWrapper::freeBuffer(native_handle_t* bufferHandle) {
296 if (mAllocatedBuffers.erase(bufferHandle)) {
297 mGrallocHal->unlock(bufferHandle);
298 mGrallocHal->freeBuffer(bufferHandle);
299 }
Brian Stackeb755f52018-09-26 14:53:25 -0700300}
301
302} // namespace android