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