1 /*
2  * Copyright (C) 2018 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 #define LOG_TAG "goog_gralloc_wrapper"
18 
19 #include "goog_gralloc_wrapper.h"
20 
21 #include <utils/Log.h>
22 
23 namespace android {
24 namespace camera_sensor_listener {
25 
26 using ::android::hardware::hidl_handle;
27 using ::android::hardware::graphics::allocator::V3_0::IAllocator;
28 using ::android::hardware::graphics::mapper::V3_0::BufferDescriptor;
29 using ::android::hardware::graphics::mapper::V3_0::Error;
30 using ::android::hardware::graphics::mapper::V3_0::IMapper;
31 
GoogGrallocWrapper()32 GoogGrallocWrapper::GoogGrallocWrapper() {
33   allocator_ = IAllocator::getService();
34   if (allocator_ == nullptr) {
35     ALOGE("%s %d Failed to get allocator service", __func__, __LINE__);
36   }
37 
38   mapper_ = IMapper::getService();
39   if (mapper_ == nullptr) {
40     ALOGE("%s %d Failed to get mapper service", __func__, __LINE__);
41   }
42   if (mapper_->isRemote()) {
43     ALOGE("%s %d Mapper is not in passthrough mode", __func__, __LINE__);
44   }
45 }
46 
~GoogGrallocWrapper()47 GoogGrallocWrapper::~GoogGrallocWrapper() {
48   for (auto buffer_handle : cloned_buffers_) {
49     auto buffer = const_cast<native_handle_t*>(buffer_handle);
50     native_handle_close(buffer);
51     native_handle_delete(buffer);
52   }
53   cloned_buffers_.clear();
54 
55   for (auto buffer_handle : imported_buffers_) {
56     auto buffer = const_cast<native_handle_t*>(buffer_handle);
57     if (mapper_->freeBuffer(buffer) != Error::NONE) {
58       ALOGE("%s %d Failed to free buffer %p", __func__, __LINE__, buffer);
59     }
60   }
61   imported_buffers_.clear();
62 }
63 
GetAllocator() const64 sp<IAllocator> GoogGrallocWrapper::GetAllocator() const {
65   return allocator_;
66 }
67 
DumpDebugInfo() const68 std::string GoogGrallocWrapper::DumpDebugInfo() const {
69   std::string debug_info;
70   allocator_->dumpDebugInfo([&debug_info](const auto& tmp_debug_info) {
71     debug_info = tmp_debug_info.c_str();
72   });
73 
74   return debug_info;
75 }
76 
CloneBuffer(const hidl_handle & raw_handle)77 const native_handle_t* GoogGrallocWrapper::CloneBuffer(
78     const hidl_handle& raw_handle) {
79   const native_handle_t* buffer_handle =
80       native_handle_clone(raw_handle.getNativeHandle());
81 
82   if (buffer_handle) {
83     cloned_buffers_.insert(buffer_handle);
84   }
85   return buffer_handle;
86 }
87 
88 // When import is false, this simply calls IAllocator::allocate. When import
89 // is true, the returned buffers are also imported into the mapper.
90 // Either case, the returned buffers must be freed with freeBuffer.
Allocate(const BufferDescriptor & descriptor,uint32_t count,bool import,uint32_t * out_stride)91 std::vector<const native_handle_t*> GoogGrallocWrapper::Allocate(
92     const BufferDescriptor& descriptor, uint32_t count, bool import,
93     uint32_t* out_stride) {
94   std::vector<const native_handle_t*> buffer_handles;
95   buffer_handles.reserve(count);
96   allocator_->allocate(
97       descriptor, count,
98       [&](const auto& tmp_error, const auto& tmp_stride,
99           const auto& tmp_buffers) {
100         if (tmp_error != Error::NONE) {
101           ALOGE("%s %d Failed to allocate buffers", __func__, __LINE__);
102         }
103         if (count != tmp_buffers.size()) {
104           ALOGE("%s %d Invalid buffer array", __func__, __LINE__);
105         }
106 
107         for (uint32_t i = 0; i < count; i++) {
108           if (import) {
109             buffer_handles.push_back(ImportBuffer(tmp_buffers[i]));
110           } else {
111             buffer_handles.push_back(CloneBuffer(tmp_buffers[i]));
112           }
113         }
114 
115         if (out_stride) {
116           *out_stride = tmp_stride;
117         }
118       });
119 
120   return buffer_handles;
121 }
122 
AllocateOneBuffer(const IMapper::BufferDescriptorInfo & descriptor_info,bool import,uint32_t * out_stride)123 const native_handle_t* GoogGrallocWrapper::AllocateOneBuffer(
124     const IMapper::BufferDescriptorInfo& descriptor_info, bool import,
125     uint32_t* out_stride) {
126   BufferDescriptor descriptor = CreateDescriptor(descriptor_info);
127   auto buffers = Allocate(descriptor, 1, import, out_stride);
128   return buffers[0];
129 }
130 
GetMapper() const131 sp<IMapper> GoogGrallocWrapper::GetMapper() const {
132   return mapper_;
133 }
134 
CreateDescriptor(const IMapper::BufferDescriptorInfo & descriptor_info)135 BufferDescriptor GoogGrallocWrapper::CreateDescriptor(
136     const IMapper::BufferDescriptorInfo& descriptor_info) {
137   BufferDescriptor descriptor;
138   mapper_->createDescriptor(
139       descriptor_info,
140       [&descriptor](const auto& tmp_error, const auto& tmp_descriptor) {
141         if (tmp_error != Error::NONE) {
142           ALOGE("Failed to create descriptor");
143         }
144         descriptor = tmp_descriptor;
145       });
146 
147   return descriptor;
148 }
149 
ImportBuffer(const hidl_handle & raw_handle)150 const native_handle_t* GoogGrallocWrapper::ImportBuffer(
151     const hidl_handle& raw_handle) {
152   const native_handle_t* buffer_handle = nullptr;
153   mapper_->importBuffer(
154       raw_handle, [&buffer_handle, &raw_handle](const auto& tmp_error,
155                                                 const auto& tmp_buffer) {
156         if (tmp_error != Error::NONE) {
157           ALOGE("%s %d Failed to import buffer %p", __func__, __LINE__,
158                 raw_handle.getNativeHandle());
159         }
160         buffer_handle = static_cast<const native_handle_t*>(tmp_buffer);
161       });
162 
163   if (buffer_handle) {
164     imported_buffers_.insert(buffer_handle);
165   }
166 
167   return buffer_handle;
168 }
169 
FreeBuffer(const native_handle_t * buffer_handle)170 void GoogGrallocWrapper::FreeBuffer(const native_handle_t* buffer_handle) {
171   auto buffer = const_cast<native_handle_t*>(buffer_handle);
172 
173   if (imported_buffers_.erase(buffer_handle)) {
174     Error error = mapper_->freeBuffer(buffer);
175     if (error != Error::NONE) {
176       ALOGE("%s %d Failed to free %p", __func__, __LINE__, buffer);
177     }
178   } else {
179     cloned_buffers_.erase(buffer_handle);
180     native_handle_close(buffer);
181     native_handle_delete(buffer);
182   }
183 }
184 
185 // We use fd instead of ::android::hardware::hidl_handle in these functions to
186 // pass fences in and out of the mapper.  The ownership of the fd is always
187 // transferred with each of these functions.
Lock(const native_handle_t * buffer_handle,uint64_t cpu_usage,const IMapper::Rect & access_region,int acquire_fence)188 void* GoogGrallocWrapper::Lock(const native_handle_t* buffer_handle,
189                                uint64_t cpu_usage,
190                                const IMapper::Rect& access_region,
191                                int acquire_fence) {
192   auto buffer = const_cast<native_handle_t*>(buffer_handle);
193 
194   NATIVE_HANDLE_DECLARE_STORAGE(acquire_fence_storage, 1, 0);
195   hidl_handle acquire_fence_handle;
196   if (acquire_fence >= 0) {
197     auto h = native_handle_init(acquire_fence_storage, 1, 0);
198     h->data[0] = acquire_fence;
199     acquire_fence_handle = h;
200   }
201 
202   void* data = nullptr;
203   mapper_->lock(buffer, cpu_usage, access_region, acquire_fence_handle,
204                 [&buffer, &data](const auto& tmp_error, const auto& tmp_data,
205                                  const auto& /*bytesPerPixel*/,
206                                  const auto& /*bytesPerStride*/) {
207                   if (tmp_error != Error::NONE) {
208                     ALOGE("Failed to lock buffer %p", buffer);
209                   } else {
210                     data = tmp_data;
211                   }
212                 });
213 
214   if (acquire_fence >= 0) {
215     close(acquire_fence);
216   }
217 
218   return data;
219 }
220 
Unlock(const native_handle_t * buffer_handle)221 int GoogGrallocWrapper::Unlock(const native_handle_t* buffer_handle) {
222   auto buffer = const_cast<native_handle_t*>(buffer_handle);
223 
224   int release_fence = -1;
225   mapper_->unlock(buffer,
226                   [&buffer, &release_fence](const auto& tmp_error,
227                                             const auto& tmp_release_fence) {
228                     if (tmp_error != Error::NONE) {
229                       ALOGE("Failed to unlock buffer %p", buffer);
230                     }
231 
232                     auto fence_handle = tmp_release_fence.getNativeHandle();
233                     if (fence_handle) {
234                       if (fence_handle->numInts != 0) {
235                         ALOGE("Invalid fence handle %p", fence_handle);
236                       }
237                       if (fence_handle->numFds == 1) {
238                         release_fence = dup(fence_handle->data[0]);
239                         if (release_fence < 0) {
240                           ALOGE("Failed to dup fence fd");
241                         }
242                       } else {
243                         if (fence_handle->numFds != 0) {
244                           ALOGE("Invalid fence handle %p", fence_handle);
245                         }
246                       }
247                     }
248                   });
249 
250   return release_fence;
251 }
252 
253 }  // namespace camera_sensor_listener
254 }  // namespace android
255