blob: 7792b31880aaf08c2beb4ca7a7bedc9fe2cc5b24 [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);
Yin-Chia Yeh97978fb2020-01-25 18:15:00 -0800185 if (!mInitialized) {
186 initializeLocked();
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700187 }
188
Marissa Walla51eb932019-06-21 09:13:35 -0700189 if (mMapperV4 != nullptr) {
190 auto ret = mMapperV4->freeBuffer(const_cast<native_handle_t*>(handle));
191 if (!ret.isOk()) {
192 ALOGE("%s: mapper freeBuffer failed: %s", __FUNCTION__, ret.description().c_str());
193 }
194 } else if (mMapperV3 != nullptr) {
Shuzhen Wang915115e2019-05-10 12:07:14 -0700195 auto ret = mMapperV3->freeBuffer(const_cast<native_handle_t*>(handle));
196 if (!ret.isOk()) {
197 ALOGE("%s: mapper freeBuffer failed: %s",
198 __FUNCTION__, ret.description().c_str());
199 }
200 } else {
201 auto ret = mMapperV2->freeBuffer(const_cast<native_handle_t*>(handle));
202 if (!ret.isOk()) {
203 ALOGE("%s: mapper freeBuffer failed: %s",
204 __FUNCTION__, ret.description().c_str());
205 }
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700206 }
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800207}
208
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700209bool HandleImporter::importFence(const native_handle_t* handle, int& fd) const {
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800210 if (handle == nullptr || handle->numFds == 0) {
211 fd = -1;
212 } else if (handle->numFds == 1) {
213 fd = dup(handle->data[0]);
214 if (fd < 0) {
215 ALOGE("failed to dup fence fd %d", handle->data[0]);
216 return false;
217 }
218 } else {
219 ALOGE("invalid fence handle with %d file descriptors",
220 handle->numFds);
221 return false;
222 }
223
224 return true;
225}
226
Yin-Chia Yeh519c1672017-04-21 14:59:31 -0700227void HandleImporter::closeFence(int fd) const {
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800228 if (fd >= 0) {
229 close(fd);
230 }
231}
232
Yuriy Romanenkod0bd4f12018-01-19 16:00:00 -0800233void* HandleImporter::lock(
234 buffer_handle_t& buf, uint64_t cpuUsage, size_t size) {
235 Mutex::Autolock lock(mLock);
236 void *ret = 0;
Yuriy Romanenkod0bd4f12018-01-19 16:00:00 -0800237
238 if (!mInitialized) {
239 initializeLocked();
240 }
241
Marissa Walla51eb932019-06-21 09:13:35 -0700242 if (mMapperV4 == nullptr && mMapperV3 == nullptr && mMapperV2 == nullptr) {
243 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
Yuriy Romanenkod0bd4f12018-01-19 16:00:00 -0800244 return ret;
245 }
246
247 hidl_handle acquireFenceHandle;
248 auto buffer = const_cast<native_handle_t*>(buf);
Marissa Walla51eb932019-06-21 09:13:35 -0700249 if (mMapperV4 != nullptr) {
250 IMapperV4::Rect accessRegion{0, 0, static_cast<int>(size), 1};
251 // No need to use bytesPerPixel and bytesPerStride because we are using
252 // an 1-D buffer and accressRegion.
253 mMapperV4->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
Marissa Wall9c5ebfc2019-11-05 14:59:27 -0800254 [&](const auto& tmpError, const auto& tmpPtr) {
Marissa Walla51eb932019-06-21 09:13:35 -0700255 if (tmpError == MapperErrorV4::NONE) {
256 ret = tmpPtr;
257 } else {
258 ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
259 }
260 });
261 } else if (mMapperV3 != nullptr) {
Shuzhen Wang915115e2019-05-10 12:07:14 -0700262 IMapperV3::Rect accessRegion { 0, 0, static_cast<int>(size), 1 };
263 // No need to use bytesPerPixel and bytesPerStride because we are using
264 // an 1-D buffer and accressRegion.
265 mMapperV3->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
266 [&](const auto& tmpError, const auto& tmpPtr, const auto& /*bytesPerPixel*/,
267 const auto& /*bytesPerStride*/) {
268 if (tmpError == MapperErrorV3::NONE) {
269 ret = tmpPtr;
270 } else {
271 ALOGE("%s: failed to lock error %d!",
272 __FUNCTION__, tmpError);
273 }
274 });
275 } else {
276 IMapper::Rect accessRegion { 0, 0, static_cast<int>(size), 1 };
277 mMapperV2->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
278 [&](const auto& tmpError, const auto& tmpPtr) {
279 if (tmpError == MapperErrorV2::NONE) {
280 ret = tmpPtr;
281 } else {
282 ALOGE("%s: failed to lock error %d!",
283 __FUNCTION__, tmpError);
284 }
285 });
286 }
Yuriy Romanenkod0bd4f12018-01-19 16:00:00 -0800287
288 ALOGV("%s: ptr %p size: %zu", __FUNCTION__, ret, size);
289 return ret;
290}
291
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700292YCbCrLayout HandleImporter::lockYCbCr(
293 buffer_handle_t& buf, uint64_t cpuUsage,
294 const IMapper::Rect& accessRegion) {
295 Mutex::Autolock lock(mLock);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700296
297 if (!mInitialized) {
298 initializeLocked();
299 }
300
Marissa Walla51eb932019-06-21 09:13:35 -0700301 if (mMapperV4 != nullptr) {
Marissa Wall9c5ebfc2019-11-05 14:59:27 -0800302 // No device currently supports IMapper 4.0 so it is safe to just return an error code here.
303 //
304 // This will be supported by a combination of lock and BufferMetadata getters. We are going
305 // to refactor all the IAllocator/IMapper versioning code into a shared library. We will
306 // then add the IMapper 4.0 lockYCbCr support then.
307 ALOGE("%s: MapperV4 doesn't support lockYCbCr directly!", __FUNCTION__);
308 return {};
Marissa Walla51eb932019-06-21 09:13:35 -0700309 }
310
Shuzhen Wang915115e2019-05-10 12:07:14 -0700311 if (mMapperV3 != nullptr) {
312 return lockYCbCrInternal<IMapperV3, MapperErrorV3>(
313 mMapperV3, buf, cpuUsage, accessRegion);
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700314 }
315
Shuzhen Wang915115e2019-05-10 12:07:14 -0700316 if (mMapperV2 != nullptr) {
317 return lockYCbCrInternal<IMapper, MapperErrorV2>(
318 mMapperV2, buf, cpuUsage, accessRegion);
319 }
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700320
Marissa Walla51eb932019-06-21 09:13:35 -0700321 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
Shuzhen Wang915115e2019-05-10 12:07:14 -0700322 return {};
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700323}
324
325int HandleImporter::unlock(buffer_handle_t& buf) {
Marissa Walla51eb932019-06-21 09:13:35 -0700326 if (mMapperV4 != nullptr) {
327 return unlockInternal<IMapperV4, MapperErrorV4>(mMapperV4, buf);
328 }
Shuzhen Wang915115e2019-05-10 12:07:14 -0700329 if (mMapperV3 != nullptr) {
330 return unlockInternal<IMapperV3, MapperErrorV3>(mMapperV3, buf);
331 }
332 if (mMapperV2 != nullptr) {
333 return unlockInternal<IMapper, MapperErrorV2>(mMapperV2, buf);
334 }
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700335
Marissa Walla51eb932019-06-21 09:13:35 -0700336 ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
Shuzhen Wang915115e2019-05-10 12:07:14 -0700337 return -1;
Yin-Chia Yeh19030592017-10-19 17:30:11 -0700338}
339
Yin-Chia Yeh248ed702017-01-23 17:27:26 -0800340} // namespace helper
341} // namespace V1_0
342} // namespace common
343} // namespace camera
344} // namespace hardware
345} // namespace android