blob: ac32c954c4b6afcb8e40c31d1cb7aeed7075f61d [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"
Steven Moreland4e7a3072017-04-06 12:15:23 -070019#include <log/log.h>
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080020
21namespace android {
22namespace hardware {
23namespace camera {
24namespace common {
25namespace V1_0 {
26namespace helper {
27
Shuzhen Wang915115e2019-05-10 12:07:14 -070028using MapperErrorV2 = android::hardware::graphics::mapper::V2_0::Error;
29using MapperErrorV3 = android::hardware::graphics::mapper::V3_0::Error;
Marissa Walla51eb932019-06-21 09:13:35 -070030using MapperErrorV4 = android::hardware::graphics::mapper::V4_0::Error;
Shuzhen Wang915115e2019-05-10 12:07:14 -070031using IMapperV3 = android::hardware::graphics::mapper::V3_0::IMapper;
Marissa Walla51eb932019-06-21 09:13:35 -070032using IMapperV4 = android::hardware::graphics::mapper::V4_0::IMapper;
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080033
Yin-Chia Yeh519c1672017-04-21 14:59:31 -070034HandleImporter::HandleImporter() : mInitialized(false) {}
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080035
Yin-Chia Yeh519c1672017-04-21 14:59:31 -070036void HandleImporter::initializeLocked() {
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080037 if (mInitialized) {
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080038 return;
39 }
40
Marissa Walla51eb932019-06-21 09:13:35 -070041 mMapperV4 = IMapperV4::getService();
42 if (mMapperV4 != nullptr) {
43 mInitialized = true;
44 return;
45 }
46
Shuzhen Wang915115e2019-05-10 12:07:14 -070047 mMapperV3 = IMapperV3::getService();
48 if (mMapperV3 != nullptr) {
49 mInitialized = true;
50 return;
51 }
52
53 mMapperV2 = IMapper::getService();
54 if (mMapperV2 == nullptr) {
Yin-Chia Yeh519c1672017-04-21 14:59:31 -070055 ALOGE("%s: cannnot acccess graphics mapper HAL!", __FUNCTION__);
56 return;
57 }
58
59 mInitialized = true;
60 return;
61}
62
63void HandleImporter::cleanup() {
Marissa Walla51eb932019-06-21 09:13:35 -070064 mMapperV4.clear();
Shuzhen Wang915115e2019-05-10 12:07:14 -070065 mMapperV3.clear();
66 mMapperV2.clear();
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080067 mInitialized = false;
68}
69
Shuzhen Wang915115e2019-05-10 12:07:14 -070070template<class M, class E>
71bool HandleImporter::importBufferInternal(const sp<M> mapper, buffer_handle_t& handle) {
72 E error;
73 buffer_handle_t importedHandle;
74 auto ret = mapper->importBuffer(
75 hidl_handle(handle),
76 [&](const auto& tmpError, const auto& tmpBufferHandle) {
77 error = tmpError;
78 importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle);
79 });
80
81 if (!ret.isOk()) {
82 ALOGE("%s: mapper importBuffer failed: %s",
83 __FUNCTION__, ret.description().c_str());
84 return false;
85 }
86
87 if (error != E::NONE) {
88 return false;
89 }
90
91 handle = importedHandle;
92 return true;
93}
94
95template<class M, class E>
96YCbCrLayout HandleImporter::lockYCbCrInternal(const sp<M> mapper, buffer_handle_t& buf,
97 uint64_t cpuUsage, const IMapper::Rect& accessRegion) {
98 hidl_handle acquireFenceHandle;
99 auto buffer = const_cast<native_handle_t*>(buf);
100 YCbCrLayout layout = {};
101
102 typename M::Rect accessRegionCopy = {accessRegion.left, accessRegion.top,
103 accessRegion.width, accessRegion.height};
104 mapper->lockYCbCr(buffer, cpuUsage, accessRegionCopy, acquireFenceHandle,
105 [&](const auto& tmpError, const auto& tmpLayout) {
106 if (tmpError == E::NONE) {
107 // Member by member copy from different versions of YCbCrLayout.
108 layout.y = tmpLayout.y;
109 layout.cb = tmpLayout.cb;
110 layout.cr = tmpLayout.cr;
111 layout.yStride = tmpLayout.yStride;
112 layout.cStride = tmpLayout.cStride;
113 layout.chromaStep = tmpLayout.chromaStep;
114 } else {
115 ALOGE("%s: failed to lockYCbCr error %d!", __FUNCTION__, tmpError);
116 }
117 });
118 return layout;
119}
120
121template<class M, class E>
122int HandleImporter::unlockInternal(const sp<M> mapper, buffer_handle_t& buf) {
123 int releaseFence = -1;
124 auto buffer = const_cast<native_handle_t*>(buf);
125
126 mapper->unlock(
127 buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
128 if (tmpError == E::NONE) {
129 auto fenceHandle = tmpReleaseFence.getNativeHandle();
130 if (fenceHandle) {
131 if (fenceHandle->numInts != 0 || fenceHandle->numFds != 1) {
132 ALOGE("%s: bad release fence numInts %d numFds %d",
133 __FUNCTION__, fenceHandle->numInts, fenceHandle->numFds);
134 return;
135 }
136 releaseFence = dup(fenceHandle->data[0]);
137 if (releaseFence < 0) {
138 ALOGE("%s: bad release fence FD %d",
139 __FUNCTION__, releaseFence);
140 }
141 }
142 } else {
143 ALOGE("%s: failed to unlock error %d!", __FUNCTION__, tmpError);
144 }
145 });
146 return releaseFence;
147}
148
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800149// In IComposer, any buffer_handle_t is owned by the caller and we need to
150// make a clone for hwcomposer2. We also need to translate empty handle
151// to nullptr. This function does that, in-place.
152bool HandleImporter::importBuffer(buffer_handle_t& handle) {
153 if (!handle->numFds && !handle->numInts) {
154 handle = nullptr;
155 return true;
156 }
157
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700158 Mutex::Autolock lock(mLock);
159 if (!mInitialized) {
160 initializeLocked();
161 }
162
Marissa Walla51eb932019-06-21 09:13:35 -0700163 if (mMapperV4 != nullptr) {
164 return importBufferInternal<IMapperV4, MapperErrorV4>(mMapperV4, handle);
165 }
166
Shuzhen Wang915115e2019-05-10 12:07:14 -0700167 if (mMapperV3 != nullptr) {
168 return importBufferInternal<IMapperV3, MapperErrorV3>(mMapperV3, handle);
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800169 }
170
Shuzhen Wang915115e2019-05-10 12:07:14 -0700171 if (mMapperV2 != nullptr) {
172 return importBufferInternal<IMapper, MapperErrorV2>(mMapperV2, handle);
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700173 }
174
Marissa Walla51eb932019-06-21 09:13:35 -0700175 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
Shuzhen Wang915115e2019-05-10 12:07:14 -0700176 return false;
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800177}
178
179void HandleImporter::freeBuffer(buffer_handle_t handle) {
180 if (!handle) {
181 return;
182 }
183
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700184 Mutex::Autolock lock(mLock);
Marissa Walla51eb932019-06-21 09:13:35 -0700185 if (mMapperV4 == nullptr && mMapperV3 == nullptr && mMapperV2 == nullptr) {
186 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700187 return;
188 }
189
Marissa Walla51eb932019-06-21 09:13:35 -0700190 if (mMapperV4 != nullptr) {
191 auto ret = mMapperV4->freeBuffer(const_cast<native_handle_t*>(handle));
192 if (!ret.isOk()) {
193 ALOGE("%s: mapper freeBuffer failed: %s", __FUNCTION__, ret.description().c_str());
194 }
195 } else if (mMapperV3 != nullptr) {
Shuzhen Wang915115e2019-05-10 12:07:14 -0700196 auto ret = mMapperV3->freeBuffer(const_cast<native_handle_t*>(handle));
197 if (!ret.isOk()) {
198 ALOGE("%s: mapper freeBuffer failed: %s",
199 __FUNCTION__, ret.description().c_str());
200 }
201 } else {
202 auto ret = mMapperV2->freeBuffer(const_cast<native_handle_t*>(handle));
203 if (!ret.isOk()) {
204 ALOGE("%s: mapper freeBuffer failed: %s",
205 __FUNCTION__, ret.description().c_str());
206 }
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700207 }
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800208}
209
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700210bool HandleImporter::importFence(const native_handle_t* handle, int& fd) const {
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800211 if (handle == nullptr || handle->numFds == 0) {
212 fd = -1;
213 } else if (handle->numFds == 1) {
214 fd = dup(handle->data[0]);
215 if (fd < 0) {
216 ALOGE("failed to dup fence fd %d", handle->data[0]);
217 return false;
218 }
219 } else {
220 ALOGE("invalid fence handle with %d file descriptors",
221 handle->numFds);
222 return false;
223 }
224
225 return true;
226}
227
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700228void HandleImporter::closeFence(int fd) const {
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800229 if (fd >= 0) {
230 close(fd);
231 }
232}
233
Yuriy Romanenkod0bd4f12018-01-19 16:00:00 -0800234void* HandleImporter::lock(
235 buffer_handle_t& buf, uint64_t cpuUsage, size_t size) {
236 Mutex::Autolock lock(mLock);
237 void *ret = 0;
Yuriy Romanenkod0bd4f12018-01-19 16:00:00 -0800238
239 if (!mInitialized) {
240 initializeLocked();
241 }
242
Marissa Walla51eb932019-06-21 09:13:35 -0700243 if (mMapperV4 == nullptr && mMapperV3 == nullptr && mMapperV2 == nullptr) {
244 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
Yuriy Romanenkod0bd4f12018-01-19 16:00:00 -0800245 return ret;
246 }
247
248 hidl_handle acquireFenceHandle;
249 auto buffer = const_cast<native_handle_t*>(buf);
Marissa Walla51eb932019-06-21 09:13:35 -0700250 if (mMapperV4 != nullptr) {
251 IMapperV4::Rect accessRegion{0, 0, static_cast<int>(size), 1};
252 // No need to use bytesPerPixel and bytesPerStride because we are using
253 // an 1-D buffer and accressRegion.
254 mMapperV4->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
Marissa Wall9c5ebfc2019-11-05 14:59:27 -0800255 [&](const auto& tmpError, const auto& tmpPtr) {
Marissa Walla51eb932019-06-21 09:13:35 -0700256 if (tmpError == MapperErrorV4::NONE) {
257 ret = tmpPtr;
258 } else {
259 ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
260 }
261 });
262 } else if (mMapperV3 != nullptr) {
Shuzhen Wang915115e2019-05-10 12:07:14 -0700263 IMapperV3::Rect accessRegion { 0, 0, static_cast<int>(size), 1 };
264 // No need to use bytesPerPixel and bytesPerStride because we are using
265 // an 1-D buffer and accressRegion.
266 mMapperV3->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
267 [&](const auto& tmpError, const auto& tmpPtr, const auto& /*bytesPerPixel*/,
268 const auto& /*bytesPerStride*/) {
269 if (tmpError == MapperErrorV3::NONE) {
270 ret = tmpPtr;
271 } else {
272 ALOGE("%s: failed to lock error %d!",
273 __FUNCTION__, tmpError);
274 }
275 });
276 } else {
277 IMapper::Rect accessRegion { 0, 0, static_cast<int>(size), 1 };
278 mMapperV2->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
279 [&](const auto& tmpError, const auto& tmpPtr) {
280 if (tmpError == MapperErrorV2::NONE) {
281 ret = tmpPtr;
282 } else {
283 ALOGE("%s: failed to lock error %d!",
284 __FUNCTION__, tmpError);
285 }
286 });
287 }
Yuriy Romanenkod0bd4f12018-01-19 16:00:00 -0800288
289 ALOGV("%s: ptr %p size: %zu", __FUNCTION__, ret, size);
290 return ret;
291}
292
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700293YCbCrLayout HandleImporter::lockYCbCr(
294 buffer_handle_t& buf, uint64_t cpuUsage,
295 const IMapper::Rect& accessRegion) {
296 Mutex::Autolock lock(mLock);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700297
298 if (!mInitialized) {
299 initializeLocked();
300 }
301
Marissa Walla51eb932019-06-21 09:13:35 -0700302 if (mMapperV4 != nullptr) {
Marissa Wall9c5ebfc2019-11-05 14:59:27 -0800303 // No device currently supports IMapper 4.0 so it is safe to just return an error code here.
304 //
305 // This will be supported by a combination of lock and BufferMetadata getters. We are going
306 // to refactor all the IAllocator/IMapper versioning code into a shared library. We will
307 // then add the IMapper 4.0 lockYCbCr support then.
308 ALOGE("%s: MapperV4 doesn't support lockYCbCr directly!", __FUNCTION__);
309 return {};
Marissa Walla51eb932019-06-21 09:13:35 -0700310 }
311
Shuzhen Wang915115e2019-05-10 12:07:14 -0700312 if (mMapperV3 != nullptr) {
313 return lockYCbCrInternal<IMapperV3, MapperErrorV3>(
314 mMapperV3, buf, cpuUsage, accessRegion);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700315 }
316
Shuzhen Wang915115e2019-05-10 12:07:14 -0700317 if (mMapperV2 != nullptr) {
318 return lockYCbCrInternal<IMapper, MapperErrorV2>(
319 mMapperV2, buf, cpuUsage, accessRegion);
320 }
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700321
Marissa Walla51eb932019-06-21 09:13:35 -0700322 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
Shuzhen Wang915115e2019-05-10 12:07:14 -0700323 return {};
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700324}
325
326int HandleImporter::unlock(buffer_handle_t& buf) {
Marissa Walla51eb932019-06-21 09:13:35 -0700327 if (mMapperV4 != nullptr) {
328 return unlockInternal<IMapperV4, MapperErrorV4>(mMapperV4, buf);
329 }
Shuzhen Wang915115e2019-05-10 12:07:14 -0700330 if (mMapperV3 != nullptr) {
331 return unlockInternal<IMapperV3, MapperErrorV3>(mMapperV3, buf);
332 }
333 if (mMapperV2 != nullptr) {
334 return unlockInternal<IMapper, MapperErrorV2>(mMapperV2, buf);
335 }
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700336
Marissa Walla51eb932019-06-21 09:13:35 -0700337 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
Shuzhen Wang915115e2019-05-10 12:07:14 -0700338 return -1;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700339}
340
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800341} // namespace helper
342} // namespace V1_0
343} // namespace common
344} // namespace camera
345} // namespace hardware
346} // namespace android