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 #include "aidl/android/hardware/graphics/common/Smpte2086.h"
23
24 namespace android {
25 namespace hardware {
26 namespace camera {
27 namespace common {
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 aidl::android::hardware::graphics::common::Smpte2086;
34 using MetadataType = android::hardware::graphics::mapper::V4_0::IMapper::MetadataType;
35 using MapperErrorV2 = android::hardware::graphics::mapper::V2_0::Error;
36 using MapperErrorV3 = android::hardware::graphics::mapper::V3_0::Error;
37 using MapperErrorV4 = android::hardware::graphics::mapper::V4_0::Error;
38 using IMapperV3 = android::hardware::graphics::mapper::V3_0::IMapper;
39 using IMapperV4 = android::hardware::graphics::mapper::V4_0::IMapper;
40
HandleImporter()41 HandleImporter::HandleImporter() : mInitialized(false) {}
42
initializeLocked()43 void HandleImporter::initializeLocked() {
44 if (mInitialized) {
45 return;
46 }
47
48 mMapperV4 = IMapperV4::getService();
49 if (mMapperV4 != nullptr) {
50 mInitialized = true;
51 return;
52 }
53
54 mMapperV3 = IMapperV3::getService();
55 if (mMapperV3 != nullptr) {
56 mInitialized = true;
57 return;
58 }
59
60 mMapperV2 = IMapper::getService();
61 if (mMapperV2 == nullptr) {
62 ALOGE("%s: cannnot acccess graphics mapper HAL!", __FUNCTION__);
63 return;
64 }
65
66 mInitialized = true;
67 return;
68 }
69
cleanup()70 void HandleImporter::cleanup() {
71 mMapperV4.clear();
72 mMapperV3.clear();
73 mMapperV2.clear();
74 mInitialized = false;
75 }
76
77 template <class M, class E>
importBufferInternal(const sp<M> mapper,buffer_handle_t & handle)78 bool HandleImporter::importBufferInternal(const sp<M> mapper, buffer_handle_t& handle) {
79 E error;
80 buffer_handle_t importedHandle;
81 auto ret = mapper->importBuffer(
82 hidl_handle(handle), [&](const auto& tmpError, const auto& tmpBufferHandle) {
83 error = tmpError;
84 importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle);
85 });
86
87 if (!ret.isOk()) {
88 ALOGE("%s: mapper importBuffer failed: %s", __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,
103 const IMapper::Rect& accessRegion) {
104 hidl_handle acquireFenceHandle;
105 auto buffer = const_cast<native_handle_t*>(buf);
106 YCbCrLayout layout = {};
107
108 typename M::Rect accessRegionCopy = {accessRegion.left, accessRegion.top, accessRegion.width,
109 accessRegion.height};
110 mapper->lockYCbCr(buffer, cpuUsage, accessRegionCopy, acquireFenceHandle,
111 [&](const auto& tmpError, const auto& tmpLayout) {
112 if (tmpError == E::NONE) {
113 // Member by member copy from different versions of YCbCrLayout.
114 layout.y = tmpLayout.y;
115 layout.cb = tmpLayout.cb;
116 layout.cr = tmpLayout.cr;
117 layout.yStride = tmpLayout.yStride;
118 layout.cStride = tmpLayout.cStride;
119 layout.chromaStep = tmpLayout.chromaStep;
120 } else {
121 ALOGE("%s: failed to lockYCbCr error %d!", __FUNCTION__, tmpError);
122 }
123 });
124 return layout;
125 }
126
isMetadataPesent(const sp<IMapperV4> mapper,const buffer_handle_t & buf,MetadataType metadataType)127 bool isMetadataPesent(const sp<IMapperV4> mapper, const buffer_handle_t& buf,
128 MetadataType metadataType) {
129 auto buffer = const_cast<native_handle_t*>(buf);
130 bool ret = false;
131 hidl_vec<uint8_t> vec;
132 mapper->get(buffer, metadataType, [&](const auto& tmpError, const auto& tmpMetadata) {
133 if (tmpError == MapperErrorV4::NONE) {
134 vec = tmpMetadata;
135 } else {
136 ALOGE("%s: failed to get metadata %d!", __FUNCTION__, tmpError);
137 }
138 });
139
140 if (vec.size() > 0) {
141 if (metadataType == gralloc4::MetadataType_Smpte2086) {
142 std::optional<Smpte2086> realSmpte2086;
143 gralloc4::decodeSmpte2086(vec, &realSmpte2086);
144 ret = realSmpte2086.has_value();
145 } else if (metadataType == gralloc4::MetadataType_Smpte2094_10) {
146 std::optional<std::vector<uint8_t>> realSmpte2094_10;
147 gralloc4::decodeSmpte2094_10(vec, &realSmpte2094_10);
148 ret = realSmpte2094_10.has_value();
149 } else if (metadataType == gralloc4::MetadataType_Smpte2094_40) {
150 std::optional<std::vector<uint8_t>> realSmpte2094_40;
151 gralloc4::decodeSmpte2094_40(vec, &realSmpte2094_40);
152 ret = realSmpte2094_40.has_value();
153 } else {
154 ALOGE("%s: Unknown metadata type!", __FUNCTION__);
155 }
156 }
157
158 return ret;
159 }
160
getPlaneLayouts(const sp<IMapperV4> mapper,buffer_handle_t & buf)161 std::vector<PlaneLayout> getPlaneLayouts(const sp<IMapperV4> mapper, buffer_handle_t& buf) {
162 auto buffer = const_cast<native_handle_t*>(buf);
163 std::vector<PlaneLayout> planeLayouts;
164 hidl_vec<uint8_t> encodedPlaneLayouts;
165 mapper->get(buffer, gralloc4::MetadataType_PlaneLayouts,
166 [&](const auto& tmpError, const auto& tmpEncodedPlaneLayouts) {
167 if (tmpError == MapperErrorV4::NONE) {
168 encodedPlaneLayouts = tmpEncodedPlaneLayouts;
169 } else {
170 ALOGE("%s: failed to get plane layouts %d!", __FUNCTION__, tmpError);
171 }
172 });
173
174 gralloc4::decodePlaneLayouts(encodedPlaneLayouts, &planeLayouts);
175
176 return planeLayouts;
177 }
178
179 template <>
lockYCbCrInternal(const sp<IMapperV4> mapper,buffer_handle_t & buf,uint64_t cpuUsage,const IMapper::Rect & accessRegion)180 YCbCrLayout HandleImporter::lockYCbCrInternal<IMapperV4, MapperErrorV4>(
181 const sp<IMapperV4> mapper, buffer_handle_t& buf, uint64_t cpuUsage,
182 const IMapper::Rect& accessRegion) {
183 hidl_handle acquireFenceHandle;
184 auto buffer = const_cast<native_handle_t*>(buf);
185 YCbCrLayout layout = {};
186 void* mapped = nullptr;
187
188 typename IMapperV4::Rect accessRegionV4 = {accessRegion.left, accessRegion.top,
189 accessRegion.width, accessRegion.height};
190 mapper->lock(buffer, cpuUsage, accessRegionV4, acquireFenceHandle,
191 [&](const auto& tmpError, const auto& tmpPtr) {
192 if (tmpError == MapperErrorV4::NONE) {
193 mapped = tmpPtr;
194 } else {
195 ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
196 }
197 });
198
199 if (mapped == nullptr) {
200 return layout;
201 }
202
203 std::vector<PlaneLayout> planeLayouts = getPlaneLayouts(mapper, buf);
204 for (const auto& planeLayout : planeLayouts) {
205 for (const auto& planeLayoutComponent : planeLayout.components) {
206 const auto& type = planeLayoutComponent.type;
207
208 if (!gralloc4::isStandardPlaneLayoutComponentType(type)) {
209 continue;
210 }
211
212 uint8_t* data = reinterpret_cast<uint8_t*>(mapped);
213 data += planeLayout.offsetInBytes;
214 data += planeLayoutComponent.offsetInBits / 8;
215
216 switch (static_cast<PlaneLayoutComponentType>(type.value)) {
217 case PlaneLayoutComponentType::Y:
218 layout.y = data;
219 layout.yStride = planeLayout.strideInBytes;
220 break;
221 case PlaneLayoutComponentType::CB:
222 layout.cb = data;
223 layout.cStride = planeLayout.strideInBytes;
224 layout.chromaStep = planeLayout.sampleIncrementInBits / 8;
225 break;
226 case PlaneLayoutComponentType::CR:
227 layout.cr = data;
228 layout.cStride = planeLayout.strideInBytes;
229 layout.chromaStep = planeLayout.sampleIncrementInBits / 8;
230 break;
231 default:
232 break;
233 }
234 }
235 }
236
237 return layout;
238 }
239
240 template <class M, class E>
unlockInternal(const sp<M> mapper,buffer_handle_t & buf)241 int HandleImporter::unlockInternal(const sp<M> mapper, buffer_handle_t& buf) {
242 int releaseFence = -1;
243 auto buffer = const_cast<native_handle_t*>(buf);
244
245 mapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
246 if (tmpError == E::NONE) {
247 auto fenceHandle = tmpReleaseFence.getNativeHandle();
248 if (fenceHandle) {
249 if (fenceHandle->numInts != 0 || fenceHandle->numFds != 1) {
250 ALOGE("%s: bad release fence numInts %d numFds %d", __FUNCTION__,
251 fenceHandle->numInts, fenceHandle->numFds);
252 return;
253 }
254 releaseFence = dup(fenceHandle->data[0]);
255 if (releaseFence < 0) {
256 ALOGE("%s: bad release fence FD %d", __FUNCTION__, releaseFence);
257 }
258 }
259 } else {
260 ALOGE("%s: failed to unlock error %d!", __FUNCTION__, tmpError);
261 }
262 });
263 return releaseFence;
264 }
265
266 // In IComposer, any buffer_handle_t is owned by the caller and we need to
267 // make a clone for hwcomposer2. We also need to translate empty handle
268 // to nullptr. This function does that, in-place.
importBuffer(buffer_handle_t & handle)269 bool HandleImporter::importBuffer(buffer_handle_t& handle) {
270 if (!handle->numFds && !handle->numInts) {
271 handle = nullptr;
272 return true;
273 }
274
275 Mutex::Autolock lock(mLock);
276 if (!mInitialized) {
277 initializeLocked();
278 }
279
280 if (mMapperV4 != nullptr) {
281 return importBufferInternal<IMapperV4, MapperErrorV4>(mMapperV4, handle);
282 }
283
284 if (mMapperV3 != nullptr) {
285 return importBufferInternal<IMapperV3, MapperErrorV3>(mMapperV3, handle);
286 }
287
288 if (mMapperV2 != nullptr) {
289 return importBufferInternal<IMapper, MapperErrorV2>(mMapperV2, handle);
290 }
291
292 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
293 return false;
294 }
295
freeBuffer(buffer_handle_t handle)296 void HandleImporter::freeBuffer(buffer_handle_t handle) {
297 if (!handle) {
298 return;
299 }
300
301 Mutex::Autolock lock(mLock);
302 if (!mInitialized) {
303 initializeLocked();
304 }
305
306 if (mMapperV4 != nullptr) {
307 auto ret = mMapperV4->freeBuffer(const_cast<native_handle_t*>(handle));
308 if (!ret.isOk()) {
309 ALOGE("%s: mapper freeBuffer failed: %s", __FUNCTION__, ret.description().c_str());
310 }
311 } else if (mMapperV3 != nullptr) {
312 auto ret = mMapperV3->freeBuffer(const_cast<native_handle_t*>(handle));
313 if (!ret.isOk()) {
314 ALOGE("%s: mapper freeBuffer failed: %s", __FUNCTION__, ret.description().c_str());
315 }
316 } else {
317 auto ret = mMapperV2->freeBuffer(const_cast<native_handle_t*>(handle));
318 if (!ret.isOk()) {
319 ALOGE("%s: mapper freeBuffer failed: %s", __FUNCTION__, ret.description().c_str());
320 }
321 }
322 }
323
importFence(const native_handle_t * handle,int & fd) const324 bool HandleImporter::importFence(const native_handle_t* handle, int& fd) const {
325 if (handle == nullptr || handle->numFds == 0) {
326 fd = -1;
327 } else if (handle->numFds == 1) {
328 fd = dup(handle->data[0]);
329 if (fd < 0) {
330 ALOGE("failed to dup fence fd %d", handle->data[0]);
331 return false;
332 }
333 } else {
334 ALOGE("invalid fence handle with %d file descriptors", handle->numFds);
335 return false;
336 }
337
338 return true;
339 }
340
closeFence(int fd) const341 void HandleImporter::closeFence(int fd) const {
342 if (fd >= 0) {
343 close(fd);
344 }
345 }
346
lock(buffer_handle_t & buf,uint64_t cpuUsage,size_t size)347 void* HandleImporter::lock(buffer_handle_t& buf, uint64_t cpuUsage, size_t size) {
348 IMapper::Rect accessRegion{0, 0, static_cast<int>(size), 1};
349 return lock(buf, cpuUsage, accessRegion);
350 }
351
lock(buffer_handle_t & buf,uint64_t cpuUsage,const IMapper::Rect & accessRegion)352 void* HandleImporter::lock(buffer_handle_t& buf, uint64_t cpuUsage,
353 const IMapper::Rect& accessRegion) {
354 Mutex::Autolock lock(mLock);
355
356 if (!mInitialized) {
357 initializeLocked();
358 }
359
360 void* ret = nullptr;
361
362 if (mMapperV4 == nullptr && mMapperV3 == nullptr && mMapperV2 == nullptr) {
363 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
364 return ret;
365 }
366
367 hidl_handle acquireFenceHandle;
368 auto buffer = const_cast<native_handle_t*>(buf);
369 if (mMapperV4 != nullptr) {
370 IMapperV4::Rect accessRegionV4{accessRegion.left, accessRegion.top, accessRegion.width,
371 accessRegion.height};
372
373 mMapperV4->lock(buffer, cpuUsage, accessRegionV4, acquireFenceHandle,
374 [&](const auto& tmpError, const auto& tmpPtr) {
375 if (tmpError == MapperErrorV4::NONE) {
376 ret = tmpPtr;
377 } else {
378 ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
379 }
380 });
381 } else if (mMapperV3 != nullptr) {
382 IMapperV3::Rect accessRegionV3{accessRegion.left, accessRegion.top, accessRegion.width,
383 accessRegion.height};
384
385 mMapperV3->lock(buffer, cpuUsage, accessRegionV3, acquireFenceHandle,
386 [&](const auto& tmpError, const auto& tmpPtr, const auto& /*bytesPerPixel*/,
387 const auto& /*bytesPerStride*/) {
388 if (tmpError == MapperErrorV3::NONE) {
389 ret = tmpPtr;
390 } else {
391 ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
392 }
393 });
394 } else {
395 mMapperV2->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
396 [&](const auto& tmpError, const auto& tmpPtr) {
397 if (tmpError == MapperErrorV2::NONE) {
398 ret = tmpPtr;
399 } else {
400 ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
401 }
402 });
403 }
404
405 ALOGV("%s: ptr %p accessRegion.top: %d accessRegion.left: %d accessRegion.width: %d "
406 "accessRegion.height: %d",
407 __FUNCTION__, ret, accessRegion.top, accessRegion.left, accessRegion.width,
408 accessRegion.height);
409 return ret;
410 }
411
lockYCbCr(buffer_handle_t & buf,uint64_t cpuUsage,const IMapper::Rect & accessRegion)412 YCbCrLayout HandleImporter::lockYCbCr(buffer_handle_t& buf, uint64_t cpuUsage,
413 const IMapper::Rect& accessRegion) {
414 Mutex::Autolock lock(mLock);
415
416 if (!mInitialized) {
417 initializeLocked();
418 }
419
420 if (mMapperV4 != nullptr) {
421 return lockYCbCrInternal<IMapperV4, MapperErrorV4>(mMapperV4, buf, cpuUsage, accessRegion);
422 }
423
424 if (mMapperV3 != nullptr) {
425 return lockYCbCrInternal<IMapperV3, MapperErrorV3>(mMapperV3, buf, cpuUsage, accessRegion);
426 }
427
428 if (mMapperV2 != nullptr) {
429 return lockYCbCrInternal<IMapper, MapperErrorV2>(mMapperV2, buf, cpuUsage, accessRegion);
430 }
431
432 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
433 return {};
434 }
435
getMonoPlanarStrideBytes(buffer_handle_t & buf,uint32_t * stride)436 status_t HandleImporter::getMonoPlanarStrideBytes(buffer_handle_t& buf, uint32_t* stride /*out*/) {
437 if (stride == nullptr) {
438 return BAD_VALUE;
439 }
440
441 Mutex::Autolock lock(mLock);
442
443 if (!mInitialized) {
444 initializeLocked();
445 }
446
447 if (mMapperV4 != nullptr) {
448 std::vector<PlaneLayout> planeLayouts = getPlaneLayouts(mMapperV4, buf);
449 if (planeLayouts.size() != 1) {
450 ALOGE("%s: Unexpected number of planes %zu!", __FUNCTION__, planeLayouts.size());
451 return BAD_VALUE;
452 }
453
454 *stride = planeLayouts[0].strideInBytes;
455 } else {
456 ALOGE("%s: mMapperV4 is null! Query not supported!", __FUNCTION__);
457 return NO_INIT;
458 }
459
460 return OK;
461 }
462
unlock(buffer_handle_t & buf)463 int HandleImporter::unlock(buffer_handle_t& buf) {
464 if (mMapperV4 != nullptr) {
465 return unlockInternal<IMapperV4, MapperErrorV4>(mMapperV4, buf);
466 }
467 if (mMapperV3 != nullptr) {
468 return unlockInternal<IMapperV3, MapperErrorV3>(mMapperV3, buf);
469 }
470 if (mMapperV2 != nullptr) {
471 return unlockInternal<IMapper, MapperErrorV2>(mMapperV2, buf);
472 }
473
474 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
475 return -1;
476 }
477
isSmpte2086Present(const buffer_handle_t & buf)478 bool HandleImporter::isSmpte2086Present(const buffer_handle_t& buf) {
479 Mutex::Autolock lock(mLock);
480
481 if (!mInitialized) {
482 initializeLocked();
483 }
484
485 if (mMapperV4 != nullptr) {
486 return isMetadataPesent(mMapperV4, buf, gralloc4::MetadataType_Smpte2086);
487 } else {
488 ALOGE("%s: mMapperV4 is null! Query not supported!", __FUNCTION__);
489 }
490
491 return false;
492 }
493
isSmpte2094_10Present(const buffer_handle_t & buf)494 bool HandleImporter::isSmpte2094_10Present(const buffer_handle_t& buf) {
495 Mutex::Autolock lock(mLock);
496
497 if (!mInitialized) {
498 initializeLocked();
499 }
500
501 if (mMapperV4 != nullptr) {
502 return isMetadataPesent(mMapperV4, buf, gralloc4::MetadataType_Smpte2094_10);
503 } else {
504 ALOGE("%s: mMapperV4 is null! Query not supported!", __FUNCTION__);
505 }
506
507 return false;
508 }
509
isSmpte2094_40Present(const buffer_handle_t & buf)510 bool HandleImporter::isSmpte2094_40Present(const buffer_handle_t& buf) {
511 Mutex::Autolock lock(mLock);
512
513 if (!mInitialized) {
514 initializeLocked();
515 }
516
517 if (mMapperV4 != nullptr) {
518 return isMetadataPesent(mMapperV4, buf, gralloc4::MetadataType_Smpte2094_40);
519 } else {
520 ALOGE("%s: mMapperV4 is null! Query not supported!", __FUNCTION__);
521 }
522
523 return false;
524 }
525
526 } // namespace helper
527 } // namespace common
528 } // namespace camera
529 } // namespace hardware
530 } // namespace android
531