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 #define LOG_TAG "HandleImporter"
18 #include "HandleImporter.h"
19
20 #include <gralloctypes/Gralloc4.h>
21 #include <log/log.h>
22
23 namespace android {
24 namespace hardware {
25 namespace camera {
26 namespace common {
27 namespace V1_0 {
28 namespace helper {
29
30 using aidl::android::hardware::graphics::common::PlaneLayout;
31 using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
32 using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
33 using MapperErrorV2 = android::hardware::graphics::mapper::V2_0::Error;
34 using MapperErrorV3 = android::hardware::graphics::mapper::V3_0::Error;
35 using MapperErrorV4 = android::hardware::graphics::mapper::V4_0::Error;
36 using IMapperV3 = android::hardware::graphics::mapper::V3_0::IMapper;
37 using IMapperV4 = android::hardware::graphics::mapper::V4_0::IMapper;
38
HandleImporter()39 HandleImporter::HandleImporter() : mInitialized(false) {}
40
initializeLocked()41 void HandleImporter::initializeLocked() {
42 if (mInitialized) {
43 return;
44 }
45
46 mMapperV4 = IMapperV4::getService();
47 if (mMapperV4 != nullptr) {
48 mInitialized = true;
49 return;
50 }
51
52 mMapperV3 = IMapperV3::getService();
53 if (mMapperV3 != nullptr) {
54 mInitialized = true;
55 return;
56 }
57
58 mMapperV2 = IMapper::getService();
59 if (mMapperV2 == nullptr) {
60 ALOGE("%s: cannnot acccess graphics mapper HAL!", __FUNCTION__);
61 return;
62 }
63
64 mInitialized = true;
65 return;
66 }
67
cleanup()68 void HandleImporter::cleanup() {
69 mMapperV4.clear();
70 mMapperV3.clear();
71 mMapperV2.clear();
72 mInitialized = false;
73 }
74
75 template<class M, class E>
importBufferInternal(const sp<M> mapper,buffer_handle_t & handle)76 bool HandleImporter::importBufferInternal(const sp<M> mapper, buffer_handle_t& handle) {
77 E error;
78 buffer_handle_t importedHandle;
79 auto ret = mapper->importBuffer(
80 hidl_handle(handle),
81 [&](const auto& tmpError, const auto& tmpBufferHandle) {
82 error = tmpError;
83 importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle);
84 });
85
86 if (!ret.isOk()) {
87 ALOGE("%s: mapper importBuffer failed: %s",
88 __FUNCTION__, ret.description().c_str());
89 return false;
90 }
91
92 if (error != E::NONE) {
93 return false;
94 }
95
96 handle = importedHandle;
97 return true;
98 }
99
100 template<class M, class E>
lockYCbCrInternal(const sp<M> mapper,buffer_handle_t & buf,uint64_t cpuUsage,const IMapper::Rect & accessRegion)101 YCbCrLayout HandleImporter::lockYCbCrInternal(const sp<M> mapper, buffer_handle_t& buf,
102 uint64_t cpuUsage, const IMapper::Rect& accessRegion) {
103 hidl_handle acquireFenceHandle;
104 auto buffer = const_cast<native_handle_t*>(buf);
105 YCbCrLayout layout = {};
106
107 typename M::Rect accessRegionCopy = {accessRegion.left, accessRegion.top,
108 accessRegion.width, accessRegion.height};
109 mapper->lockYCbCr(buffer, cpuUsage, accessRegionCopy, acquireFenceHandle,
110 [&](const auto& tmpError, const auto& tmpLayout) {
111 if (tmpError == E::NONE) {
112 // Member by member copy from different versions of YCbCrLayout.
113 layout.y = tmpLayout.y;
114 layout.cb = tmpLayout.cb;
115 layout.cr = tmpLayout.cr;
116 layout.yStride = tmpLayout.yStride;
117 layout.cStride = tmpLayout.cStride;
118 layout.chromaStep = tmpLayout.chromaStep;
119 } else {
120 ALOGE("%s: failed to lockYCbCr error %d!", __FUNCTION__, tmpError);
121 }
122 });
123 return layout;
124 }
125
126 template <>
lockYCbCrInternal(const sp<IMapperV4> mapper,buffer_handle_t & buf,uint64_t cpuUsage,const IMapper::Rect & accessRegion)127 YCbCrLayout HandleImporter::lockYCbCrInternal<IMapperV4, MapperErrorV4>(
128 const sp<IMapperV4> mapper, buffer_handle_t& buf, uint64_t cpuUsage,
129 const IMapper::Rect& accessRegion) {
130 hidl_handle acquireFenceHandle;
131 auto buffer = const_cast<native_handle_t*>(buf);
132 YCbCrLayout layout = {};
133 void* mapped = nullptr;
134
135 typename IMapperV4::Rect accessRegionV4 = {accessRegion.left, accessRegion.top,
136 accessRegion.width, accessRegion.height};
137 mapper->lock(buffer, cpuUsage, accessRegionV4, acquireFenceHandle,
138 [&](const auto& tmpError, const auto& tmpPtr) {
139 if (tmpError == MapperErrorV4::NONE) {
140 mapped = tmpPtr;
141 } else {
142 ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
143 }
144 });
145
146 if (mapped == nullptr) {
147 return layout;
148 }
149
150 hidl_vec<uint8_t> encodedPlaneLayouts;
151 mapper->get(buffer, gralloc4::MetadataType_PlaneLayouts,
152 [&](const auto& tmpError, const auto& tmpEncodedPlaneLayouts) {
153 if (tmpError == MapperErrorV4::NONE) {
154 encodedPlaneLayouts = tmpEncodedPlaneLayouts;
155 } else {
156 ALOGE("%s: failed to get plane layouts %d!", __FUNCTION__, tmpError);
157 }
158 });
159
160 std::vector<PlaneLayout> planeLayouts;
161 gralloc4::decodePlaneLayouts(encodedPlaneLayouts, &planeLayouts);
162
163 for (const auto& planeLayout : planeLayouts) {
164 for (const auto& planeLayoutComponent : planeLayout.components) {
165 const auto& type = planeLayoutComponent.type;
166
167 if (!gralloc4::isStandardPlaneLayoutComponentType(type)) {
168 continue;
169 }
170
171 uint8_t* data = reinterpret_cast<uint8_t*>(mapped);
172 data += planeLayout.offsetInBytes;
173 data += planeLayoutComponent.offsetInBits / 8;
174
175 switch (static_cast<PlaneLayoutComponentType>(type.value)) {
176 case PlaneLayoutComponentType::Y:
177 layout.y = data;
178 layout.yStride = planeLayout.strideInBytes;
179 break;
180 case PlaneLayoutComponentType::CB:
181 layout.cb = data;
182 layout.cStride = planeLayout.strideInBytes;
183 layout.chromaStep = planeLayout.sampleIncrementInBits / 8;
184 break;
185 case PlaneLayoutComponentType::CR:
186 layout.cr = data;
187 layout.cStride = planeLayout.strideInBytes;
188 layout.chromaStep = planeLayout.sampleIncrementInBits / 8;
189 break;
190 default:
191 break;
192 }
193 }
194 }
195
196 return layout;
197 }
198
199 template<class M, class E>
unlockInternal(const sp<M> mapper,buffer_handle_t & buf)200 int HandleImporter::unlockInternal(const sp<M> mapper, buffer_handle_t& buf) {
201 int releaseFence = -1;
202 auto buffer = const_cast<native_handle_t*>(buf);
203
204 mapper->unlock(
205 buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
206 if (tmpError == E::NONE) {
207 auto fenceHandle = tmpReleaseFence.getNativeHandle();
208 if (fenceHandle) {
209 if (fenceHandle->numInts != 0 || fenceHandle->numFds != 1) {
210 ALOGE("%s: bad release fence numInts %d numFds %d",
211 __FUNCTION__, fenceHandle->numInts, fenceHandle->numFds);
212 return;
213 }
214 releaseFence = dup(fenceHandle->data[0]);
215 if (releaseFence < 0) {
216 ALOGE("%s: bad release fence FD %d",
217 __FUNCTION__, releaseFence);
218 }
219 }
220 } else {
221 ALOGE("%s: failed to unlock error %d!", __FUNCTION__, tmpError);
222 }
223 });
224 return releaseFence;
225 }
226
227 // In IComposer, any buffer_handle_t is owned by the caller and we need to
228 // make a clone for hwcomposer2. We also need to translate empty handle
229 // to nullptr. This function does that, in-place.
importBuffer(buffer_handle_t & handle)230 bool HandleImporter::importBuffer(buffer_handle_t& handle) {
231 if (!handle->numFds && !handle->numInts) {
232 handle = nullptr;
233 return true;
234 }
235
236 Mutex::Autolock lock(mLock);
237 if (!mInitialized) {
238 initializeLocked();
239 }
240
241 if (mMapperV4 != nullptr) {
242 return importBufferInternal<IMapperV4, MapperErrorV4>(mMapperV4, handle);
243 }
244
245 if (mMapperV3 != nullptr) {
246 return importBufferInternal<IMapperV3, MapperErrorV3>(mMapperV3, handle);
247 }
248
249 if (mMapperV2 != nullptr) {
250 return importBufferInternal<IMapper, MapperErrorV2>(mMapperV2, handle);
251 }
252
253 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
254 return false;
255 }
256
freeBuffer(buffer_handle_t handle)257 void HandleImporter::freeBuffer(buffer_handle_t handle) {
258 if (!handle) {
259 return;
260 }
261
262 Mutex::Autolock lock(mLock);
263 if (!mInitialized) {
264 initializeLocked();
265 }
266
267 if (mMapperV4 != nullptr) {
268 auto ret = mMapperV4->freeBuffer(const_cast<native_handle_t*>(handle));
269 if (!ret.isOk()) {
270 ALOGE("%s: mapper freeBuffer failed: %s", __FUNCTION__, ret.description().c_str());
271 }
272 } else if (mMapperV3 != nullptr) {
273 auto ret = mMapperV3->freeBuffer(const_cast<native_handle_t*>(handle));
274 if (!ret.isOk()) {
275 ALOGE("%s: mapper freeBuffer failed: %s",
276 __FUNCTION__, ret.description().c_str());
277 }
278 } else {
279 auto ret = mMapperV2->freeBuffer(const_cast<native_handle_t*>(handle));
280 if (!ret.isOk()) {
281 ALOGE("%s: mapper freeBuffer failed: %s",
282 __FUNCTION__, ret.description().c_str());
283 }
284 }
285 }
286
importFence(const native_handle_t * handle,int & fd) const287 bool HandleImporter::importFence(const native_handle_t* handle, int& fd) const {
288 if (handle == nullptr || handle->numFds == 0) {
289 fd = -1;
290 } else if (handle->numFds == 1) {
291 fd = dup(handle->data[0]);
292 if (fd < 0) {
293 ALOGE("failed to dup fence fd %d", handle->data[0]);
294 return false;
295 }
296 } else {
297 ALOGE("invalid fence handle with %d file descriptors",
298 handle->numFds);
299 return false;
300 }
301
302 return true;
303 }
304
closeFence(int fd) const305 void HandleImporter::closeFence(int fd) const {
306 if (fd >= 0) {
307 close(fd);
308 }
309 }
310
lock(buffer_handle_t & buf,uint64_t cpuUsage,size_t size)311 void* HandleImporter::lock(
312 buffer_handle_t& buf, uint64_t cpuUsage, size_t size) {
313 IMapper::Rect accessRegion{0, 0, static_cast<int>(size), 1};
314 return lock(buf, cpuUsage, accessRegion);
315 }
316
lock(buffer_handle_t & buf,uint64_t cpuUsage,const IMapper::Rect & accessRegion)317 void* HandleImporter::lock(buffer_handle_t& buf, uint64_t cpuUsage,
318 const IMapper::Rect& accessRegion) {
319 Mutex::Autolock lock(mLock);
320
321 if (!mInitialized) {
322 initializeLocked();
323 }
324
325 void* ret = nullptr;
326
327 if (mMapperV4 == nullptr && mMapperV3 == nullptr && mMapperV2 == nullptr) {
328 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
329 return ret;
330 }
331
332 hidl_handle acquireFenceHandle;
333 auto buffer = const_cast<native_handle_t*>(buf);
334 if (mMapperV4 != nullptr) {
335 IMapperV4::Rect accessRegionV4{accessRegion.left, accessRegion.top, accessRegion.width,
336 accessRegion.height};
337
338 mMapperV4->lock(buffer, cpuUsage, accessRegionV4, acquireFenceHandle,
339 [&](const auto& tmpError, const auto& tmpPtr) {
340 if (tmpError == MapperErrorV4::NONE) {
341 ret = tmpPtr;
342 } else {
343 ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
344 }
345 });
346 } else if (mMapperV3 != nullptr) {
347 IMapperV3::Rect accessRegionV3{accessRegion.left, accessRegion.top, accessRegion.width,
348 accessRegion.height};
349
350 mMapperV3->lock(buffer, cpuUsage, accessRegionV3, acquireFenceHandle,
351 [&](const auto& tmpError, const auto& tmpPtr, const auto& /*bytesPerPixel*/,
352 const auto& /*bytesPerStride*/) {
353 if (tmpError == MapperErrorV3::NONE) {
354 ret = tmpPtr;
355 } else {
356 ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
357 }
358 });
359 } else {
360 mMapperV2->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
361 [&](const auto& tmpError, const auto& tmpPtr) {
362 if (tmpError == MapperErrorV2::NONE) {
363 ret = tmpPtr;
364 } else {
365 ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
366 }
367 });
368 }
369
370 ALOGV("%s: ptr %p accessRegion.top: %d accessRegion.left: %d accessRegion.width: %d "
371 "accessRegion.height: %d",
372 __FUNCTION__, ret, accessRegion.top, accessRegion.left, accessRegion.width,
373 accessRegion.height);
374 return ret;
375 }
376
lockYCbCr(buffer_handle_t & buf,uint64_t cpuUsage,const IMapper::Rect & accessRegion)377 YCbCrLayout HandleImporter::lockYCbCr(
378 buffer_handle_t& buf, uint64_t cpuUsage,
379 const IMapper::Rect& accessRegion) {
380 Mutex::Autolock lock(mLock);
381
382 if (!mInitialized) {
383 initializeLocked();
384 }
385
386 if (mMapperV4 != nullptr) {
387 return lockYCbCrInternal<IMapperV4, MapperErrorV4>(mMapperV4, buf, cpuUsage, accessRegion);
388 }
389
390 if (mMapperV3 != nullptr) {
391 return lockYCbCrInternal<IMapperV3, MapperErrorV3>(
392 mMapperV3, buf, cpuUsage, accessRegion);
393 }
394
395 if (mMapperV2 != nullptr) {
396 return lockYCbCrInternal<IMapper, MapperErrorV2>(
397 mMapperV2, buf, cpuUsage, accessRegion);
398 }
399
400 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
401 return {};
402 }
403
unlock(buffer_handle_t & buf)404 int HandleImporter::unlock(buffer_handle_t& buf) {
405 if (mMapperV4 != nullptr) {
406 return unlockInternal<IMapperV4, MapperErrorV4>(mMapperV4, buf);
407 }
408 if (mMapperV3 != nullptr) {
409 return unlockInternal<IMapperV3, MapperErrorV3>(mMapperV3, buf);
410 }
411 if (mMapperV2 != nullptr) {
412 return unlockInternal<IMapper, MapperErrorV2>(mMapperV2, buf);
413 }
414
415 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
416 return -1;
417 }
418
419 } // namespace helper
420 } // namespace V1_0
421 } // namespace common
422 } // namespace camera
423 } // namespace hardware
424 } // namespace android
425