• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <aidl/android/hardware/graphics/allocator/IAllocator.h>
20 #include <aidlcommonsupport/NativeHandle.h>
21 #include <android/binder_manager.h>
22 #include <android/hardware/graphics/allocator/2.0/IAllocator.h>
23 #include <android/hardware/graphics/allocator/3.0/IAllocator.h>
24 #include <android/hardware/graphics/allocator/4.0/IAllocator.h>
25 #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>
28 #include <android/hardware/graphics/mapper/4.0/IMapper.h>
29 
30 #include <utils/Log.h>
31 
32 #include <cinttypes>
33 #include <memory>
34 #include <type_traits>
35 
36 using IAllocatorAidl = ::aidl::android::hardware::graphics::allocator::IAllocator;
37 using IAllocator2 = ::android::hardware::graphics::allocator::V2_0::IAllocator;
38 using IAllocator3 = ::android::hardware::graphics::allocator::V3_0::IAllocator;
39 using IAllocator4 = ::android::hardware::graphics::allocator::V4_0::IAllocator;
40 using IMapper2 = ::android::hardware::graphics::mapper::V2_0::IMapper;
41 using IMapper2_1 = ::android::hardware::graphics::mapper::V2_1::IMapper;
42 using IMapper3 = ::android::hardware::graphics::mapper::V3_0::IMapper;
43 using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
44 
45 using Error2 = ::android::hardware::graphics::mapper::V2_0::Error;
46 using Error3 = ::android::hardware::graphics::mapper::V3_0::Error;
47 using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
48 
49 using ::aidl::android::hardware::common::NativeHandle;
50 using ::aidl::android::hardware::graphics::allocator::AllocationResult;
51 
52 using ::android::hardware::graphics::common::V1_0::BufferUsage;
53 using ::android::hardware::graphics::common::V1_0::PixelFormat;
54 
55 using ::android::hardware::hidl_handle;
56 using ::android::hardware::hidl_string;
57 using ::android::hardware::hidl_vec;
58 
59 namespace android {
60 
61 // 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)
66 class IGrallocHalWrapper {
67   public:
68     virtual ~IGrallocHalWrapper() = default;
69 
70     // IAllocator
71     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 
79 namespace {
80 
failed(Error2 error)81 bool failed(Error2 error) {
82     return (error != Error2::NONE);
83 }
failed(Error3 error)84 bool failed(Error3 error) {
85     return (error != Error3::NONE);
86 }
failed(Error4 error)87 bool failed(Error4 error) {
88     return (error != Error4::NONE);
89 }
90 
91 template <typename>
92 struct 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
96 template <typename ReturnType, typename ClassT, typename Arg1, typename... OtherArgs>
97 struct FirstArg<ReturnType (ClassT::*)(Arg1, OtherArgs...)> {
98     using type = Arg1;
99 };
100 
101 // Alias to FirstArg which also removes any reference type and const associated
102 template <typename T>
103 using BaseTypeOfFirstArg = typename std::remove_const<
104         typename std::remove_reference<typename FirstArg<T>::type>::type>::type;
105 
106 // 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.
108 template <typename AllocatorT, typename MapperT,
109           template <typename> typename AllocatorWrapperT = sp>
110 class GrallocHalWrapper : public IGrallocHalWrapper {
111   public:
GrallocHalWrapper(const AllocatorWrapperT<AllocatorT> & allocator,const sp<MapperT> & mapper)112     GrallocHalWrapper(const AllocatorWrapperT<AllocatorT>& allocator, const sp<MapperT>& mapper)
113         : mAllocator(allocator), mMapper(mapper) {
114         if (mapper->isRemote()) {
115             ALOGE("Mapper is in passthrough mode");
116         }
117     }
118 
119     virtual native_handle_t* allocate(uint32_t size) override;
120     virtual void freeBuffer(native_handle_t* bufferHandle) override;
121 
122     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);
128     AllocatorWrapperT<AllocatorT> mAllocator;
129     sp<MapperT> mMapper;
130 
131     // 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);
137     native_handle_t* importBuffer(const hidl_handle& rawHandle);
138 };
139 
140 template <>
allocate(uint32_t size)141 native_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 
165 template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
allocate(uint32_t size)166 native_handle_t* GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::allocate(
167         uint32_t size) {
168     constexpr uint32_t kBufferCount = 1;
169     BufferDescriptorT descriptor = getDescriptor(size);
170     native_handle_t* bufferHandle = nullptr;
171 
172     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);
184     return bufferHandle;
185 }
186 
187 template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
freeBuffer(native_handle_t * bufferHandle)188 void GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::freeBuffer(
189         native_handle_t* bufferHandle) {
190     auto error = mMapper->freeBuffer(bufferHandle);
191     if (!error.isOk() || failed(error)) {
192         ALOGE("Failed to free buffer %p", bufferHandle);
193     }
194 }
195 
196 template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
197 typename GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::BufferDescriptorT
getDescriptor(uint32_t size)198 GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::getDescriptor(uint32_t size) {
199     typename MapperT::BufferDescriptorInfo descriptorInfo = {
200             .width = size,
201             .height = 1,
202             .layerCount = 1,
203             .format = static_cast<decltype(descriptorInfo.format)>(PixelFormat::BLOB),
204             .usage = kBufferUsage,
205     };
206 
207     BufferDescriptorT descriptor;
208     auto callback = [&](auto error, const BufferDescriptorT& tmpDescriptor) {
209         if (failed(error)) {
210             ALOGE("Failed to create descriptor: %" PRId32, static_cast<int32_t>(error));
211         } else {
212             descriptor = tmpDescriptor;
213         }
214     };
215 
216     mMapper->createDescriptor(descriptorInfo, callback);
217     return descriptor;
218 }
219 
220 template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
importBuffer(const hidl_handle & rawHandle)221 native_handle_t* GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::importBuffer(
222         const hidl_handle& rawHandle) {
223     native_handle_t* bufferHandle = nullptr;
224 
225     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     });
233 
234     return bufferHandle;
235 }
236 
237 template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
lock(native_handle_t * bufferHandle)238 void* GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::lock(
239         native_handle_t* bufferHandle) {
240     // 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
243 
244     void* data = nullptr;
245     mMapper->lock(bufferHandle, kBufferUsage, accessRegion, acquireFenceHandle,
246                   [&](auto error, void* tmpData, ...) {  // V3/4 pass extra args we don't use
247                       if (failed(error)) {
248                           ALOGE("Failed to lock buffer %p: %" PRId32, bufferHandle,
249                                 static_cast<int32_t>(error));
250                       } else {
251                           data = tmpData;
252                       }
253                   });
254 
255     return data;
256 }
257 
258 template <typename AllocatorT, typename MapperT, template <typename> typename AllocatorWrapperT>
unlock(native_handle_t * bufferHandle)259 void GrallocHalWrapper<AllocatorT, MapperT, AllocatorWrapperT>::unlock(
260         native_handle_t* bufferHandle) {
261     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));
265         }
266     });
267 }
268 
269 }  // anonymous namespace
270 
GrallocWrapper()271 GrallocWrapper::GrallocWrapper() {
272     sp<IAllocator4> allocator4 = IAllocator4::getService();
273     sp<IMapper4> mapper4 = IMapper4::getService();
274 
275     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");
291         mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
292                 new GrallocHalWrapper<IAllocator4, IMapper4>(allocator4, mapper4));
293     } else {
294         ALOGD("Graphics HALs 4.0 not found (allocator %d mapper %d), falling back to 3.0",
295               (allocator4 != nullptr), (mapper4 != nullptr));
296 
297         sp<IAllocator3> allocator3 = IAllocator3::getService();
298         sp<IMapper3> mapper3 = IMapper3::getService();
299 
300         if (allocator3 != nullptr && mapper3 != nullptr) {
301             mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
302                     new GrallocHalWrapper<IAllocator3, IMapper3>(allocator3, mapper3));
303         } else {
304             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             }
320         }
321     }
322 }
323 
~GrallocWrapper()324 GrallocWrapper::~GrallocWrapper() {
325     for (auto bufferHandle : mAllocatedBuffers) {
326         mGrallocHal->unlock(bufferHandle);
327         mGrallocHal->freeBuffer(bufferHandle);
328     }
329     mAllocatedBuffers.clear();
330 }
331 
allocate(uint32_t size)332 std::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 
freeBuffer(native_handle_t * bufferHandle)347 void GrallocWrapper::freeBuffer(native_handle_t* bufferHandle) {
348     if (mAllocatedBuffers.erase(bufferHandle)) {
349         mGrallocHal->unlock(bufferHandle);
350         mGrallocHal->freeBuffer(bufferHandle);
351     }
352 }
353 
354 }  // namespace android
355