1 /*
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
17 #include "GrallocWrapper.h"
18
19 #include <android/hardware/graphics/allocator/2.0/IAllocator.h>
20 #include <android/hardware/graphics/allocator/3.0/IAllocator.h>
21 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
22 #include <android/hardware/graphics/mapper/2.1/IMapper.h>
23 #include <android/hardware/graphics/mapper/3.0/IMapper.h>
24
25 #include <utils/Log.h>
26
27 #include <cinttypes>
28 #include <type_traits>
29
30 using IAllocator2 = ::android::hardware::graphics::allocator::V2_0::IAllocator;
31 using IAllocator3 = ::android::hardware::graphics::allocator::V3_0::IAllocator;
32 using IMapper2 = ::android::hardware::graphics::mapper::V2_0::IMapper;
33 using IMapper2_1 = ::android::hardware::graphics::mapper::V2_1::IMapper;
34 using IMapper3 = ::android::hardware::graphics::mapper::V3_0::IMapper;
35
36 using Error2 = ::android::hardware::graphics::mapper::V2_0::Error;
37 using Error3 = ::android::hardware::graphics::mapper::V3_0::Error;
38
39 using ::android::hardware::graphics::common::V1_0::BufferUsage;
40 using ::android::hardware::graphics::common::V1_0::PixelFormat;
41
42 // This is a typedef to the same underlying type across v2.0 and v3.0
43 using ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;
44
45 using ::android::hardware::hidl_handle;
46 using ::android::hardware::hidl_string;
47 using ::android::hardware::hidl_vec;
48
49 namespace android {
50
51 // Since we use the same APIs across allocator/mapper HALs but they have major
52 // version differences (meaning they are not related through inheritance), we
53 // create a common interface abstraction for the IAllocator + IMapper combination
54 // (major versions need to match in the current HALs, e.g. IAllocator 3.0 needs to
55 // be paired with IMapper 3.0, so these are tied together)
56 class IGrallocHalWrapper {
57 public:
58 virtual ~IGrallocHalWrapper() = default;
59
60 // IAllocator
61 virtual std::string dumpDebugInfo() = 0;
62 virtual native_handle_t* allocate(uint32_t size) = 0;
63 virtual void freeBuffer(native_handle_t* bufferHandle) = 0;
64
65 // IMapper
66 virtual void* lock(native_handle_t* bufferHandle) = 0;
67 virtual void unlock(native_handle_t* bufferHandle) = 0;
68 };
69
70 namespace {
71
failed(Error2 error)72 bool failed(Error2 error) {
73 return (error != Error2::NONE);
74 }
failed(Error3 error)75 bool failed(Error3 error) {
76 return (error != Error3::NONE);
77 }
78
79 // Since all the type and function names are the same for the things we use across the major HAL
80 // versions, we use template magic to avoid repeating ourselves.
81 template <typename AllocatorT, typename MapperT>
82 class GrallocHalWrapper : public IGrallocHalWrapper {
83 public:
GrallocHalWrapper(const sp<AllocatorT> & allocator,const sp<MapperT> & mapper)84 GrallocHalWrapper(const sp<AllocatorT>& allocator, const sp<MapperT>& mapper)
85 : mAllocator(allocator), mMapper(mapper) {
86 if (mapper->isRemote()) {
87 ALOGE("Mapper is in passthrough mode");
88 }
89 }
90
91 virtual std::string dumpDebugInfo() override;
92 virtual native_handle_t* allocate(uint32_t size) override;
93 virtual void freeBuffer(native_handle_t* bufferHandle) override;
94
95 virtual void* lock(native_handle_t* bufferHandle) override;
96 virtual void unlock(native_handle_t* bufferHandle) override;
97
98 private:
99 static constexpr uint64_t kBufferUsage =
100 static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::CPU_READ_OFTEN);
101 sp<AllocatorT> mAllocator;
102 sp<MapperT> mMapper;
103
104 BufferDescriptor getDescriptor(uint32_t size);
105 native_handle_t* importBuffer(const hidl_handle& rawHandle);
106 };
107
108 template <typename AllocatorT, typename MapperT>
dumpDebugInfo()109 std::string GrallocHalWrapper<AllocatorT, MapperT>::dumpDebugInfo() {
110 std::string debugInfo;
111 mAllocator->dumpDebugInfo([&](const hidl_string& tmpDebugInfo) { debugInfo = tmpDebugInfo; });
112 return debugInfo;
113 }
114
115 template <typename AllocatorT, typename MapperT>
allocate(uint32_t size)116 native_handle_t* GrallocHalWrapper<AllocatorT, MapperT>::allocate(uint32_t size) {
117 constexpr uint32_t kBufferCount = 1;
118 BufferDescriptor descriptor = getDescriptor(size);
119 native_handle_t* bufferHandle = nullptr;
120
121 auto callback = [&](auto error, uint32_t /*stride*/, const hidl_vec<hidl_handle>& buffers) {
122 if (failed(error)) {
123 ALOGE("Failed to allocate buffer: %" PRId32, static_cast<int32_t>(error));
124 } else if (buffers.size() != kBufferCount) {
125 ALOGE("Invalid buffer array size (got %zu, expected %" PRIu32 ")", buffers.size(),
126 kBufferCount);
127 } else {
128 bufferHandle = importBuffer(buffers[0]);
129 }
130 };
131
132 mAllocator->allocate(descriptor, kBufferCount, callback);
133 return bufferHandle;
134 }
135
136 template <typename AllocatorT, typename MapperT>
freeBuffer(native_handle_t * bufferHandle)137 void GrallocHalWrapper<AllocatorT, MapperT>::freeBuffer(native_handle_t* bufferHandle) {
138 auto error = mMapper->freeBuffer(bufferHandle);
139 if (!error.isOk() || failed(error)) {
140 ALOGE("Failed to free buffer %p", bufferHandle);
141 }
142 }
143
144 template <typename AllocatorT, typename MapperT>
getDescriptor(uint32_t size)145 BufferDescriptor GrallocHalWrapper<AllocatorT, MapperT>::getDescriptor(uint32_t size) {
146 typename MapperT::BufferDescriptorInfo descriptorInfo = {
147 .width = size,
148 .height = 1,
149 .layerCount = 1,
150 .format = static_cast<decltype(descriptorInfo.format)>(PixelFormat::BLOB),
151 .usage = kBufferUsage,
152 };
153
154 BufferDescriptor descriptor;
155 auto callback = [&](auto error, const BufferDescriptor& tmpDescriptor) {
156 if (failed(error)) {
157 ALOGE("Failed to create descriptor: %" PRId32, static_cast<int32_t>(error));
158 } else {
159 descriptor = tmpDescriptor;
160 }
161 };
162
163 mMapper->createDescriptor(descriptorInfo, callback);
164 return descriptor;
165 }
166
167 template <typename AllocatorT, typename MapperT>
importBuffer(const hidl_handle & rawHandle)168 native_handle_t* GrallocHalWrapper<AllocatorT, MapperT>::importBuffer(
169 const hidl_handle& rawHandle) {
170 native_handle_t* bufferHandle = nullptr;
171
172 mMapper->importBuffer(rawHandle, [&](auto error, void* tmpBuffer) {
173 if (failed(error)) {
174 ALOGE("Failed to import buffer %p: %" PRId32, rawHandle.getNativeHandle(),
175 static_cast<int32_t>(error));
176 } else {
177 bufferHandle = static_cast<native_handle_t*>(tmpBuffer);
178 }
179 });
180
181 return bufferHandle;
182 }
183
184 template <typename AllocatorT, typename MapperT>
lock(native_handle_t * bufferHandle)185 void* GrallocHalWrapper<AllocatorT, MapperT>::lock(native_handle_t* bufferHandle) {
186 // Per the HAL, all-zeros Rect means the entire buffer
187 typename MapperT::Rect accessRegion = {};
188 hidl_handle acquireFenceHandle; // No fence needed, already safe to lock
189
190 void* data = nullptr;
191 mMapper->lock(bufferHandle, kBufferUsage, accessRegion, acquireFenceHandle,
192 [&](auto error, void* tmpData, ...) { // V3_0 passes extra args we don't use
193 if (failed(error)) {
194 ALOGE("Failed to lock buffer %p: %" PRId32, bufferHandle,
195 static_cast<int32_t>(error));
196 } else {
197 data = tmpData;
198 }
199 });
200
201 return data;
202 }
203
204 template <typename AllocatorT, typename MapperT>
unlock(native_handle_t * bufferHandle)205 void GrallocHalWrapper<AllocatorT, MapperT>::unlock(native_handle_t* bufferHandle) {
206 mMapper->unlock(bufferHandle, [&](auto error, const hidl_handle& /*releaseFence*/) {
207 if (failed(error)) {
208 ALOGE("Failed to unlock buffer %p: %" PRId32, bufferHandle,
209 static_cast<int32_t>(error));
210 }
211 });
212 }
213
214 } // anonymous namespace
215
GrallocWrapper()216 GrallocWrapper::GrallocWrapper() {
217 sp<IAllocator3> allocator3 = IAllocator3::getService();
218 sp<IMapper3> mapper3 = IMapper3::getService();
219
220 if (allocator3 != nullptr && mapper3 != nullptr) {
221 mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
222 new GrallocHalWrapper<IAllocator3, IMapper3>(allocator3, mapper3));
223 } else {
224 ALOGD("Graphics HALs 3.0 not found (allocator %d mapper %d), falling back to 2.x",
225 (allocator3 != nullptr), (mapper3 != nullptr));
226
227 sp<IAllocator2> allocator2 = IAllocator2::getService();
228 sp<IMapper2> mapper2 = IMapper2_1::getService();
229 if (mapper2 == nullptr) {
230 mapper2 = IMapper2::getService();
231 }
232
233 if (allocator2 != nullptr && mapper2 != nullptr) {
234 mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
235 new GrallocHalWrapper<IAllocator2, IMapper2>(allocator2, mapper2));
236 } else {
237 ALOGE("Couldn't open 2.x/3.0 graphics HALs (2.x allocator %d mapper %d)",
238 (allocator2 != nullptr), (mapper2 != nullptr));
239 }
240 }
241 }
242
~GrallocWrapper()243 GrallocWrapper::~GrallocWrapper() {
244 for (auto bufferHandle : mAllocatedBuffers) {
245 mGrallocHal->unlock(bufferHandle);
246 mGrallocHal->freeBuffer(bufferHandle);
247 }
248 mAllocatedBuffers.clear();
249 }
250
dumpDebugInfo()251 std::string GrallocWrapper::dumpDebugInfo() {
252 return mGrallocHal->dumpDebugInfo();
253 }
254
allocate(uint32_t size)255 std::pair<native_handle_t*, void*> GrallocWrapper::allocate(uint32_t size) {
256 native_handle_t* bufferHandle = mGrallocHal->allocate(size);
257 void* buffer = nullptr;
258 if (bufferHandle) {
259 buffer = mGrallocHal->lock(bufferHandle);
260 if (buffer) {
261 mAllocatedBuffers.insert(bufferHandle);
262 } else {
263 mGrallocHal->freeBuffer(bufferHandle);
264 bufferHandle = nullptr;
265 }
266 }
267 return std::make_pair<>(bufferHandle, buffer);
268 }
269
freeBuffer(native_handle_t * bufferHandle)270 void GrallocWrapper::freeBuffer(native_handle_t* bufferHandle) {
271 if (mAllocatedBuffers.erase(bufferHandle)) {
272 mGrallocHal->unlock(bufferHandle);
273 mGrallocHal->freeBuffer(bufferHandle);
274 }
275 }
276
277 } // namespace android
278