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