blob: 7fcf52330c7135293921a55f07291c0081476fa3 [file] [log] [blame]
Yin-Chia Yeh248ed702017-01-23 17:27:26 -08001/*
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"
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080018#include "HandleImporter.h"
Jason Macnakeda6dca2020-04-15 15:20:59 -070019
20#include <gralloctypes/Gralloc4.h>
Steven Moreland4e7a3072017-04-06 12:15:23 -070021#include <log/log.h>
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080022
23namespace android {
24namespace hardware {
25namespace camera {
26namespace common {
27namespace V1_0 {
28namespace helper {
29
Jason Macnakeda6dca2020-04-15 15:20:59 -070030using aidl::android::hardware::graphics::common::PlaneLayout;
31using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
32using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
Shuzhen Wang915115e2019-05-10 12:07:14 -070033using MapperErrorV2 = android::hardware::graphics::mapper::V2_0::Error;
34using MapperErrorV3 = android::hardware::graphics::mapper::V3_0::Error;
Marissa Walla51eb932019-06-21 09:13:35 -070035using MapperErrorV4 = android::hardware::graphics::mapper::V4_0::Error;
Shuzhen Wang915115e2019-05-10 12:07:14 -070036using IMapperV3 = android::hardware::graphics::mapper::V3_0::IMapper;
Marissa Walla51eb932019-06-21 09:13:35 -070037using IMapperV4 = android::hardware::graphics::mapper::V4_0::IMapper;
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080038
Yin-Chia Yeh519c1672017-04-21 14:59:31 -070039HandleImporter::HandleImporter() : mInitialized(false) {}
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080040
Yin-Chia Yeh519c1672017-04-21 14:59:31 -070041void HandleImporter::initializeLocked() {
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080042 if (mInitialized) {
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080043 return;
44 }
45
Marissa Walla51eb932019-06-21 09:13:35 -070046 mMapperV4 = IMapperV4::getService();
47 if (mMapperV4 != nullptr) {
48 mInitialized = true;
49 return;
50 }
51
Shuzhen Wang915115e2019-05-10 12:07:14 -070052 mMapperV3 = IMapperV3::getService();
53 if (mMapperV3 != nullptr) {
54 mInitialized = true;
55 return;
56 }
57
58 mMapperV2 = IMapper::getService();
59 if (mMapperV2 == nullptr) {
Yin-Chia Yeh519c1672017-04-21 14:59:31 -070060 ALOGE("%s: cannnot acccess graphics mapper HAL!", __FUNCTION__);
61 return;
62 }
63
64 mInitialized = true;
65 return;
66}
67
68void HandleImporter::cleanup() {
Marissa Walla51eb932019-06-21 09:13:35 -070069 mMapperV4.clear();
Shuzhen Wang915115e2019-05-10 12:07:14 -070070 mMapperV3.clear();
71 mMapperV2.clear();
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080072 mInitialized = false;
73}
74
Shuzhen Wang915115e2019-05-10 12:07:14 -070075template<class M, class E>
76bool 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
100template<class M, class E>
101YCbCrLayout 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
Emilian Peev6a2572b2021-05-24 16:51:17 -0700126std::vector<PlaneLayout> getPlaneLayouts(const sp<IMapperV4> mapper, buffer_handle_t& buf) {
127 auto buffer = const_cast<native_handle_t*>(buf);
128 std::vector<PlaneLayout> planeLayouts;
129 hidl_vec<uint8_t> encodedPlaneLayouts;
130 mapper->get(buffer, gralloc4::MetadataType_PlaneLayouts,
131 [&](const auto& tmpError, const auto& tmpEncodedPlaneLayouts) {
132 if (tmpError == MapperErrorV4::NONE) {
133 encodedPlaneLayouts = tmpEncodedPlaneLayouts;
134 } else {
135 ALOGE("%s: failed to get plane layouts %d!", __FUNCTION__, tmpError);
136 }
137 });
138
139 gralloc4::decodePlaneLayouts(encodedPlaneLayouts, &planeLayouts);
140
141 return planeLayouts;
142}
143
Jason Macnakeda6dca2020-04-15 15:20:59 -0700144template <>
145YCbCrLayout HandleImporter::lockYCbCrInternal<IMapperV4, MapperErrorV4>(
146 const sp<IMapperV4> mapper, buffer_handle_t& buf, uint64_t cpuUsage,
147 const IMapper::Rect& accessRegion) {
148 hidl_handle acquireFenceHandle;
149 auto buffer = const_cast<native_handle_t*>(buf);
150 YCbCrLayout layout = {};
151 void* mapped = nullptr;
152
153 typename IMapperV4::Rect accessRegionV4 = {accessRegion.left, accessRegion.top,
154 accessRegion.width, accessRegion.height};
155 mapper->lock(buffer, cpuUsage, accessRegionV4, acquireFenceHandle,
156 [&](const auto& tmpError, const auto& tmpPtr) {
157 if (tmpError == MapperErrorV4::NONE) {
158 mapped = tmpPtr;
159 } else {
160 ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
161 }
162 });
163
164 if (mapped == nullptr) {
165 return layout;
166 }
167
Emilian Peev6a2572b2021-05-24 16:51:17 -0700168 std::vector<PlaneLayout> planeLayouts = getPlaneLayouts(mapper, buf);
Jason Macnakeda6dca2020-04-15 15:20:59 -0700169 for (const auto& planeLayout : planeLayouts) {
170 for (const auto& planeLayoutComponent : planeLayout.components) {
171 const auto& type = planeLayoutComponent.type;
172
173 if (!gralloc4::isStandardPlaneLayoutComponentType(type)) {
174 continue;
175 }
176
177 uint8_t* data = reinterpret_cast<uint8_t*>(mapped);
178 data += planeLayout.offsetInBytes;
179 data += planeLayoutComponent.offsetInBits / 8;
180
181 switch (static_cast<PlaneLayoutComponentType>(type.value)) {
182 case PlaneLayoutComponentType::Y:
183 layout.y = data;
184 layout.yStride = planeLayout.strideInBytes;
185 break;
186 case PlaneLayoutComponentType::CB:
187 layout.cb = data;
188 layout.cStride = planeLayout.strideInBytes;
189 layout.chromaStep = planeLayout.sampleIncrementInBits / 8;
190 break;
191 case PlaneLayoutComponentType::CR:
192 layout.cr = data;
193 layout.cStride = planeLayout.strideInBytes;
194 layout.chromaStep = planeLayout.sampleIncrementInBits / 8;
195 break;
196 default:
197 break;
198 }
199 }
200 }
201
202 return layout;
203}
204
Shuzhen Wang915115e2019-05-10 12:07:14 -0700205template<class M, class E>
206int HandleImporter::unlockInternal(const sp<M> mapper, buffer_handle_t& buf) {
207 int releaseFence = -1;
208 auto buffer = const_cast<native_handle_t*>(buf);
209
210 mapper->unlock(
211 buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
212 if (tmpError == E::NONE) {
213 auto fenceHandle = tmpReleaseFence.getNativeHandle();
214 if (fenceHandle) {
215 if (fenceHandle->numInts != 0 || fenceHandle->numFds != 1) {
216 ALOGE("%s: bad release fence numInts %d numFds %d",
217 __FUNCTION__, fenceHandle->numInts, fenceHandle->numFds);
218 return;
219 }
220 releaseFence = dup(fenceHandle->data[0]);
221 if (releaseFence < 0) {
222 ALOGE("%s: bad release fence FD %d",
223 __FUNCTION__, releaseFence);
224 }
225 }
226 } else {
227 ALOGE("%s: failed to unlock error %d!", __FUNCTION__, tmpError);
228 }
229 });
230 return releaseFence;
231}
232
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800233// In IComposer, any buffer_handle_t is owned by the caller and we need to
234// make a clone for hwcomposer2. We also need to translate empty handle
235// to nullptr. This function does that, in-place.
236bool HandleImporter::importBuffer(buffer_handle_t& handle) {
237 if (!handle->numFds && !handle->numInts) {
238 handle = nullptr;
239 return true;
240 }
241
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700242 Mutex::Autolock lock(mLock);
243 if (!mInitialized) {
244 initializeLocked();
245 }
246
Marissa Walla51eb932019-06-21 09:13:35 -0700247 if (mMapperV4 != nullptr) {
248 return importBufferInternal<IMapperV4, MapperErrorV4>(mMapperV4, handle);
249 }
250
Shuzhen Wang915115e2019-05-10 12:07:14 -0700251 if (mMapperV3 != nullptr) {
252 return importBufferInternal<IMapperV3, MapperErrorV3>(mMapperV3, handle);
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800253 }
254
Shuzhen Wang915115e2019-05-10 12:07:14 -0700255 if (mMapperV2 != nullptr) {
256 return importBufferInternal<IMapper, MapperErrorV2>(mMapperV2, handle);
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700257 }
258
Marissa Walla51eb932019-06-21 09:13:35 -0700259 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
Shuzhen Wang915115e2019-05-10 12:07:14 -0700260 return false;
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800261}
262
263void HandleImporter::freeBuffer(buffer_handle_t handle) {
264 if (!handle) {
265 return;
266 }
267
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700268 Mutex::Autolock lock(mLock);
Yin-Chia Yeh97978fb2020-01-25 18:15:00 -0800269 if (!mInitialized) {
270 initializeLocked();
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700271 }
272
Marissa Walla51eb932019-06-21 09:13:35 -0700273 if (mMapperV4 != nullptr) {
274 auto ret = mMapperV4->freeBuffer(const_cast<native_handle_t*>(handle));
275 if (!ret.isOk()) {
276 ALOGE("%s: mapper freeBuffer failed: %s", __FUNCTION__, ret.description().c_str());
277 }
278 } else if (mMapperV3 != nullptr) {
Shuzhen Wang915115e2019-05-10 12:07:14 -0700279 auto ret = mMapperV3->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 } else {
285 auto ret = mMapperV2->freeBuffer(const_cast<native_handle_t*>(handle));
286 if (!ret.isOk()) {
287 ALOGE("%s: mapper freeBuffer failed: %s",
288 __FUNCTION__, ret.description().c_str());
289 }
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700290 }
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800291}
292
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700293bool HandleImporter::importFence(const native_handle_t* handle, int& fd) const {
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800294 if (handle == nullptr || handle->numFds == 0) {
295 fd = -1;
296 } else if (handle->numFds == 1) {
297 fd = dup(handle->data[0]);
298 if (fd < 0) {
299 ALOGE("failed to dup fence fd %d", handle->data[0]);
300 return false;
301 }
302 } else {
303 ALOGE("invalid fence handle with %d file descriptors",
304 handle->numFds);
305 return false;
306 }
307
308 return true;
309}
310
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700311void HandleImporter::closeFence(int fd) const {
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800312 if (fd >= 0) {
313 close(fd);
314 }
315}
316
Yuriy Romanenkod0bd4f12018-01-19 16:00:00 -0800317void* HandleImporter::lock(
318 buffer_handle_t& buf, uint64_t cpuUsage, size_t size) {
Jason Macnakf2c9ed12020-04-20 14:43:58 -0700319 IMapper::Rect accessRegion{0, 0, static_cast<int>(size), 1};
320 return lock(buf, cpuUsage, accessRegion);
321}
322
323void* HandleImporter::lock(buffer_handle_t& buf, uint64_t cpuUsage,
324 const IMapper::Rect& accessRegion) {
Yuriy Romanenkod0bd4f12018-01-19 16:00:00 -0800325 Mutex::Autolock lock(mLock);
Yuriy Romanenkod0bd4f12018-01-19 16:00:00 -0800326
327 if (!mInitialized) {
328 initializeLocked();
329 }
330
Jason Macnakf2c9ed12020-04-20 14:43:58 -0700331 void* ret = nullptr;
332
Marissa Walla51eb932019-06-21 09:13:35 -0700333 if (mMapperV4 == nullptr && mMapperV3 == nullptr && mMapperV2 == nullptr) {
334 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
Yuriy Romanenkod0bd4f12018-01-19 16:00:00 -0800335 return ret;
336 }
337
338 hidl_handle acquireFenceHandle;
339 auto buffer = const_cast<native_handle_t*>(buf);
Marissa Walla51eb932019-06-21 09:13:35 -0700340 if (mMapperV4 != nullptr) {
Jason Macnakf2c9ed12020-04-20 14:43:58 -0700341 IMapperV4::Rect accessRegionV4{accessRegion.left, accessRegion.top, accessRegion.width,
342 accessRegion.height};
343
344 mMapperV4->lock(buffer, cpuUsage, accessRegionV4, acquireFenceHandle,
Marissa Wall9c5ebfc2019-11-05 14:59:27 -0800345 [&](const auto& tmpError, const auto& tmpPtr) {
Marissa Walla51eb932019-06-21 09:13:35 -0700346 if (tmpError == MapperErrorV4::NONE) {
347 ret = tmpPtr;
348 } else {
349 ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
350 }
351 });
352 } else if (mMapperV3 != nullptr) {
Jason Macnakf2c9ed12020-04-20 14:43:58 -0700353 IMapperV3::Rect accessRegionV3{accessRegion.left, accessRegion.top, accessRegion.width,
354 accessRegion.height};
355
356 mMapperV3->lock(buffer, cpuUsage, accessRegionV3, acquireFenceHandle,
357 [&](const auto& tmpError, const auto& tmpPtr, const auto& /*bytesPerPixel*/,
358 const auto& /*bytesPerStride*/) {
359 if (tmpError == MapperErrorV3::NONE) {
360 ret = tmpPtr;
361 } else {
362 ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
363 }
364 });
Shuzhen Wang915115e2019-05-10 12:07:14 -0700365 } else {
Shuzhen Wang915115e2019-05-10 12:07:14 -0700366 mMapperV2->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
367 [&](const auto& tmpError, const auto& tmpPtr) {
368 if (tmpError == MapperErrorV2::NONE) {
369 ret = tmpPtr;
370 } else {
Jason Macnakf2c9ed12020-04-20 14:43:58 -0700371 ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
Shuzhen Wang915115e2019-05-10 12:07:14 -0700372 }
373 });
374 }
Yuriy Romanenkod0bd4f12018-01-19 16:00:00 -0800375
Jason Macnakf2c9ed12020-04-20 14:43:58 -0700376 ALOGV("%s: ptr %p accessRegion.top: %d accessRegion.left: %d accessRegion.width: %d "
377 "accessRegion.height: %d",
378 __FUNCTION__, ret, accessRegion.top, accessRegion.left, accessRegion.width,
379 accessRegion.height);
Yuriy Romanenkod0bd4f12018-01-19 16:00:00 -0800380 return ret;
381}
382
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700383YCbCrLayout HandleImporter::lockYCbCr(
384 buffer_handle_t& buf, uint64_t cpuUsage,
385 const IMapper::Rect& accessRegion) {
386 Mutex::Autolock lock(mLock);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700387
388 if (!mInitialized) {
389 initializeLocked();
390 }
391
Marissa Walla51eb932019-06-21 09:13:35 -0700392 if (mMapperV4 != nullptr) {
Jason Macnakeda6dca2020-04-15 15:20:59 -0700393 return lockYCbCrInternal<IMapperV4, MapperErrorV4>(mMapperV4, buf, cpuUsage, accessRegion);
Marissa Walla51eb932019-06-21 09:13:35 -0700394 }
395
Shuzhen Wang915115e2019-05-10 12:07:14 -0700396 if (mMapperV3 != nullptr) {
397 return lockYCbCrInternal<IMapperV3, MapperErrorV3>(
398 mMapperV3, buf, cpuUsage, accessRegion);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700399 }
400
Shuzhen Wang915115e2019-05-10 12:07:14 -0700401 if (mMapperV2 != nullptr) {
402 return lockYCbCrInternal<IMapper, MapperErrorV2>(
403 mMapperV2, buf, cpuUsage, accessRegion);
404 }
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700405
Marissa Walla51eb932019-06-21 09:13:35 -0700406 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
Shuzhen Wang915115e2019-05-10 12:07:14 -0700407 return {};
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700408}
409
Emilian Peev6a2572b2021-05-24 16:51:17 -0700410status_t HandleImporter::getMonoPlanarStrideBytes(buffer_handle_t &buf, uint32_t *stride /*out*/) {
411 if (stride == nullptr) {
412 return BAD_VALUE;
413 }
414
415 Mutex::Autolock lock(mLock);
416
417 if (!mInitialized) {
418 initializeLocked();
419 }
420
421 if (mMapperV4 != nullptr) {
422 std::vector<PlaneLayout> planeLayouts = getPlaneLayouts(mMapperV4, buf);
423 if (planeLayouts.size() != 1) {
424 ALOGE("%s: Unexpected number of planes %zu!", __FUNCTION__, planeLayouts.size());
425 return BAD_VALUE;
426 }
427
428 *stride = planeLayouts[0].strideInBytes;
429 } else {
430 ALOGE("%s: mMapperV4 is null! Query not supported!", __FUNCTION__);
431 return NO_INIT;
432 }
433
434 return OK;
435}
436
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700437int HandleImporter::unlock(buffer_handle_t& buf) {
Marissa Walla51eb932019-06-21 09:13:35 -0700438 if (mMapperV4 != nullptr) {
439 return unlockInternal<IMapperV4, MapperErrorV4>(mMapperV4, buf);
440 }
Shuzhen Wang915115e2019-05-10 12:07:14 -0700441 if (mMapperV3 != nullptr) {
442 return unlockInternal<IMapperV3, MapperErrorV3>(mMapperV3, buf);
443 }
444 if (mMapperV2 != nullptr) {
445 return unlockInternal<IMapper, MapperErrorV2>(mMapperV2, buf);
446 }
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700447
Marissa Walla51eb932019-06-21 09:13:35 -0700448 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
Shuzhen Wang915115e2019-05-10 12:07:14 -0700449 return -1;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700450}
451
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800452} // namespace helper
453} // namespace V1_0
454} // namespace common
455} // namespace camera
456} // namespace hardware
457} // namespace android