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